Dev:Source/Architecture/SDNA Notes
Notes on SDNA
Feel free to comment on the talk page.
WIP REASON:
Needs to be merged with Dev:Doc/Blender_Source/DNAStructs
|
Architecture documentation:
Be sure to read through http://www.blender.org/development/architecture/
|
Everyone who wants to add features to the blender core, will be confronted with this weirdo system. I called it 'Struct DNA' or SDNA in the code. This is essential information that should have been documented long ago... but it's never too late to make docs, er!
The system was divised to support Blender's file format, and internal library/database system. It allows Blender to do a runtime checking of the contents of the Structure data. This enables a few nice features:
- you can just add or remove variables from structures, or add/remove complete new structures, without damaging backward *and* forward compatiblity of files
- you can use this for Python or smart buttons in Blender, to check run-time which variable or structure is being provided
All of Blender's structures that can be saved to a file, are described with the SDNA. This is basically a long string of codes, with the structure and variable names and types. The 'makesdna' utility takes care of this, it has a built-in list of .h header files, that are read and converted to the SDNA file. When a file is saved, the functions that write structs look up the structure code and write that in the chunk header (struct BHead, writefile.c). At the end of the file, the full SDNA description file is appended to the .blend file, to make the file backward/upward compatible.
Each compiled Blender has an SDNA description as well. When a file is read, the SDNA of the file is compared with the SDNA of the Blender executable. Structures that differ get flagged, and converted while read.
Allowed conversions (changes) are:
- if a name is identical, but the type differs it tries to convert. Only conversions that make sense happen (e.g. short->int, or int->float, etc). Otherwise it is set at zero.
- a new variable is always initialized zero
- dimensions of arrays get fixed (e.g. [3][3] to [4][4])
- pointer sizes corrected (32 bits, 64 bits)
- char to float: divided by 255 automatically
- changes in structures within structures (within structures etc) work fine
At the time, I didn't include automatic 'padding' in the system... it's the platform dependent habit of compilers to include empty spaces in structures, to conform alignment of data. For example, at 32 bit SGI an 'int' should always start at an address that can be divided by 4. When you design a struct like this:
struct XYZ {
char x_flag;
float x;
char y_flag;
float y;
char z_flag;
float z;
}
The actual length of the structure will be 6x4=24 bytes. Even worse, a struct like this:
struct ABC {
char a;
}
is 8 bytes at an Alpha and other 64 bit systems, and 4 bytes at 32 bits OS's. As all new machines are 64, the target is that, even if you develop with 32 bit one.
Therefore, for correct SDNA structures in Blender, you have to design the structures with explicit padding, for all supported systems. The compiler should NEVER had to do the padding for you. These are the rules:
- the main purpose is to design SDNA structs in such a way that they're properly "8 byte aligned" for 64 bits system, which automatically will become "4 byte aligned" for 32 bits systems.
- meaning, for the counting below, pretend pointers are 8 bytes long, also for 32 bits systems.
- structures are always multiples of 8 bytes in size
- structs within structs start at an 8-dividable location
- pointers start at an 8-dividable location, unless the previous variable is a pointer!
- ints/floats start at a 4-dividable location
- shorts start at a 2-dividable location
If you can't manage this, just instert 'pad' variables in structures.
You'll find them in Blender more, it's meant to be free space that can be used for later. Do not use (store data in) 'pad' variables in Blender!!!