Compiler ignoriert #pragma pack
-
Hallo zusammen
Ich habe folgende Struktur:// ******************************************** struct "Light" ******************************************* // This struct describes a single light source. Be aware that no member of this structure must cross // a 128-Bit boundary, otherwise this structure cannot simply be copied to the GPU registers. // Author: Samuel Lörtscher // ******************************************************************************************************* #pragma pack(push,16) struct Light{ public: // --------------------------------------- public dynamic members --------------------------------------- Color Color; // color Vector3 Position; // position vector Vector3 Direction; // direction vector float32 Theta; // inner cone angle float32 Phi; // outer cone angle float32 Fallof; // fallof float32 Attenuation0; // the first attenuation float32 Attenuation1; // the second attenuation float32 Attenuation2; // the third attenuation // ------------------------------------------------------------------------------------------------------ }; #pragma pack(pop) // *******************************************************************************************************Diese sollte doch nun 72Bytes gross sein? Tatsächlich ist sie aber nur 64Bytes gross, so als würde ich das pack nicht machen? Hat vielleicht jemand eine Idee, wie ich den Compiler (Visual Studio 2010) dazu zwingen kann, diese Struktur korrekt auszurichten?
Mfg Samuel
-
Ishildur schrieb:
Diese sollte doch nun 68Bytes gross sein? Tatsächlich ist sie aber nur 64Bytes gross, so als würde ich das pack nicht machen? Hat vielleicht jemand eine Idee, wie ich den Compiler (Visual Studio 2010) dazu zwingen kann, diese Struktur korrekt auszurichten?
1. Ich nehme an, dass Color ein ARGB Wert ist mit 4x 32 Bit Zahlen.
2. Ich nehme an, dass Vector3 eine Struktur mit 3x 32 Bit Zahlen ist.
3. Dann wäre 64 Bytes für mich absolut in Ordnung. Wieso sollten es 68 Bytes sein, wenn es auf ein vielfaches von 16 Bytes packen sollen?Grüssli
-
wenn es auf ein vielfaches von 16 Bytes packen sollen?
Oje, in diesem Fall habe ich wohl packed falsch verstanden. Nein was ich brauche ist ein packing, bei welcher keine der Membervariablen eine 128bit Grenze überschreitet:
struct Light{ public: // --------------------------------------- public dynamic members --------------------------------------- Color Color; // --> neuer 128bit Bereich (0 padding) Vector3 Position; // --> neuer 128bit Bereich (0 byte padding) Vector3 Direction; // --> neuer 128bit Bereich (4 byte padding) float32 Theta; // --> neuer 128bit Bereich (4 byte padding) float32 Phi; // float32 Fallof; // float32 Attenuation0; // float32 Attenuation1; // --> neuer 128bit Bereich (0 padding) float32 Attenuation2; // // ------------------------------------------------------------------------------------------------------ };Würde man bspw. nach Position kein padding von 1 byte machen, würde Direction anschliessend auf 2 128Bit Register der Grafikkarte verteilt und das ist nix gut!
Weisst du, wie man sowas machen kann? Ich meine mir ist schon klar, dass ich einfach Bytes hineinpflastern kann, aber ich meine eine etwas elegantere Möglichkeit, also nicht
struct A{ Vector3 B; uint32 Padding0; Vector3 C; uint32 Padding1; };oder sowas
P.S.
Hier sieht man die Packing rules von HLSL http://msdn.microsoft.com/en-us/library/bb509632(v=VS.85).aspx
Natürlich müssen meine C++ Strukturen identisch gepackt werden, damit ich sie in die Konstantenregistern der Vertex- und Pixelshader kopieren kann, ohne in jedem Frame das Ganze auseinanderfrickeln zu müssen...
-
Grundsätzlich so:
#include <iostream> struct Color { float a, r, g, b; }; struct Vector3 { float x, y, z; }; typedef float float32; struct Light { __declspec(align(16)) Color Color; // color __declspec(align(16)) Vector3 Position; // position vector __declspec(align(16)) Vector3 Direction; // direction vector __declspec(align(16)) float32 Theta; // inner cone angle __declspec(align(16)) float32 Phi; // outer cone angle __declspec(align(16)) float32 Fallof; // fallof __declspec(align(16)) float32 Attenuation0; // the first attenuation __declspec(align(16)) float32 Attenuation1; // the second attenuation __declspec(align(16)) float32 Attenuation2; // the third attenuation }; int main() { std::cout << sizeof(Light) << std::endl; std::cin.get(); }Aber das wäre dann logischerweise eine Struktur mit 144 Bytes (9 x 16 Bytes).
Grüssli
-
Du willst doch, dass die Vector3-Member deiner Struktur 16 statt 12 Bytes breit sind, wenn ich dich richtig verstanden habe. Das könntest du bei der Definition von Vector3 so erreichen:
__declspec(align(16)) struct Vector3 { //... };EDIT: Ok, Dravere macht's besser. Ich wusste gar nicht, dass man das pro Member notieren kann (hab aber auch nur mal davon gelesen und es nie angewendet).
-
@Dravere
Leider hast du mich noch nicht ganz verstanden
Theta, Phi, Fallof und Attenuation0 sollen nicht nach 128-bit ausgerichtet sein sondern nur Theta (sonst würde ja als Folge jeder einzelne Wert in einem separaten Register stehen (soviele Register habe ich gar nicht). Diese vier sollen in einem einzigen Register gepackt werden. Genauso wie Attenuation1 und Attenuation2.
Wichtig ist auch dass jtzt nicht die erste Komponente von Direction in die letze Komponete des Registers gepackt wird, wo bereits Position drinn steht, sondern in einem neuen Register anfangen usw...
-
Ishildur schrieb:
@Dravere
Leider hast du mich noch nicht ganz verstanden
Theta, Phi, Fallof und Attenuation0 sollen nicht nach 128-bit ausgerichtet sein sondern nur Theta (sonst würde ja als Folge jeder einzelne Wert in einem separaten Register stehen (soviele Register habe ich gar nicht). Diese vier sollen in einem einzigen Register gepackt werden. Genauso wie Attenuation1 und Attenuation2.
Wichtig ist auch dass jtzt nicht die erste Komponente von Direction in die letze Komponete des Registers gepackt wird, wo bereits Position drinn steht, sondern in einem neuen Register anfangen usw...Ja aber das erreichst du doch, wenn du nur die beiden Vector3-Member auf 16 Bytes ausrichtest (mit Däckelspeck...
).struct Light { Color Color; // color __declspec(align(16)) Vector3 Position; // position vector __declspec(align(16)) Vector3 Direction; // direction vector float32 Theta; // inner cone angle float32 Phi; // outer cone angle float32 Fallof; // fallof float32 Attenuation0; // the first attenuation float32 Attenuation1; // the second attenuation float32 Attenuation2; // the third attenuation };Oder liege ich da falsch?
-
_matze schrieb:
Oder liege ich da falsch?
Hätte ich jetzt auch gesagt. Allerdings wird die Struktur dann 80 Bytes gross werden, weil er nochmals 8 Bytes ganz am Ende einfügt. Aber das sollte hoffentlich kein Problem darstellen.
Grüssli