Memory alignment requirements of various data?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Paco
Posts: 54
Joined: Sun Oct 09, 2005 6:53 pm

Memory alignment requirements of various data?

Post by Paco »

As posted in the GetMemory() thread, I keep having random problems if I don't make sure that all my Gu-related data is aligned to 16 bytes: matrices, vertex arrays, display lists... When I dont align them with __attribute__((aligned(16))), rendering tends to fail depending on how many commands have been inserted in the Gu display list (which is big enough so overflow is not an issue). Sometimes things fail to display, sometimes I get an entire graphics reset (video mode goes back to 16-bit, indicating a malformed command stream).

I'm *fairly* sure my code doesn't contain any buffer overruns or dangling pointers.

All the samples seem to blindly declare everything aligned. In psptypes.h, some types are declared with the __attribute__((aligned(16))) modifier as well (notably, ScePspFMatrix4). Looking at the sceGuSetMatrix function, I have no idea why this would be necessary, since the function just copies each float into the command list.

Can someone please describe what exactly is the alignment requirements of different data, and the alignment that the compiler and libraries guarantee?
Paco
chp
Posts: 313
Joined: Wed Jun 23, 2004 7:16 am

Post by chp »

When I first did the samples, I wasn't sure how much dependant on alignment the PSP was, so I just took a safe route. Vertex-buffers, index-buffers have to be word-aligned (4 bytes), while textures have to be qword-aligned (16 bytes). A good example of buffers not aligned to qword-boundaries is the new splinesurface-sample I wrote today, which does not do anything special with the buffers.

ScePspFMatrix4 is qword-aligned because that's what a requirement placed by the VFPU, otherwise you couldn't load the entire matrix into a set of registers (MIPS is very picky with alignments). VFPU-powered matrix-routines is on the way.
GE Dominator
Paco
Posts: 54
Joined: Sun Oct 09, 2005 6:53 pm

Post by Paco »

I see... But my code fails to agree. :( Some more questions:

- I tried to #define ALIGN_16 __attribute__((aligned(16))), and I would get different results if I used the macro (crash exactly as if the macro wasn't there) or the actual __attribute__ (things worked). Is this normal?

- I understand VFPU requires QWORD alignment, but why does sceGuSetMatrix() need aligned matrices if it's not actually doing any math with them? It's not just the "safe route", I tried passing an unaligned matrix (properly cast to ScePspFMatrix4*) and rendering broke apart. Might this be due to some compiler optimization inside sceGuSetMatrix(), that takes advantage of the alignment declared for the parameter (even if the actual hardware doesnt need such alignment)?

- It's a pity that ScePspFMatrix4Unaligned and ScePspFMatrix4 are completely different types, even though the only change is the alignment of ScePspFMatrix4. Would the following make the types compatible? (in psptypes.h)

Code: Select all

typedef struct ScePspFMatrix4Unaligned ScePspFMatrix4 __attribute__((aligned(16)));
I know, C blokes are used to typecasting everything and the dog, but I'm a fairly strict C++ dude. :) To me, an Aligned piece data should be directly usable in places that ask for Unaligned, but being completely separate declarations makes this impossible without a typecast.
Paco
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

I'm not quite sure what you're doing, but __attribute__((aligned(16))) doesn't magically make all uses of the type aligned. If you allocate some memory which isn't 16-byte aligned and cast the pointer to a type with an aligned attribute, it isn't going to make the pointer aligned; you still need to do bitwise manipulation on the pointer itself. The aligned attribute is used by the compiler when it gets to control the alignment of the variable (like with a static/global variable, or when assigning offsets in a structure).

Also, you can specify the aligned attribute on an actual variable declaration, rather than making it a property of the type:

Code: Select all

struct foo must_be_aligned __attribute__((aligned(16)));
I'm not sure why you would see any difference between inserting the __attribute__ literally vs. with a macro. gcc might be picky about where the attribute appears in the declaration, which would affect its meaning.
Post Reply