Okay, es fällt mir schwer, einen Bool zu packen und in einen konstanten Hlsl-Puffer auszurichten, und ich bin mir nicht sicher, warum.
Hier ist der Puffer in hlsl
cbuffer MaterialBuffer : register(b1) {
float3 materialDiffuseAlbedo;
float materialSpecularExponent;
float3 materialSpecularAlbedo;
bool isTextured;
};
Und hier ist es in c ++
struct GeometryBufferPass_MaterialBuffer {
XMFLOAT3 diffuse;
float specularExponent;
XMFLOAT3 specular;
bool isTextured;
};
Ich habe versucht, den Bool zu bewegen und die Struktur auf alle möglichen Arten aufzufüllen, ohne Glück. Was ist der richtige Weg, um dies zu tun?
directx
hlsl
data-structure
KlashnikovKid
quelle
quelle
Antworten:
Aus Effizienzgründen werden konstante Puffer so zugeordnet, dass die Werte die GPU-Register nicht überspannen . Jedes Register hat eine Größe von vier Gleitkommazahlen (16 Byte), daher müssen konstante Pufferstrukturen ein Vielfaches davon auf der GPU sein. Ihre C ++ - Struktur sollte entsprechend aufgefüllt werden, wenn Sie sie als Komfort für die Zuordnung von Daten verwenden möchten (dies ist nicht immer gut skalierbar).
Ihr Problem ist also, dass ein HLSL-Boolescher Wert vier Bytes, aber ein Byte auf der CPU-Seite (in Ihrer spezifischen Implementierung) umfasst. Dies führt dazu, dass Ihre C ++ - Struktur nicht richtig ausgerichtet wird: Das signifikante Bit eines booleschen Werts (die 0 oder 1, die wichtig ist) wird im am wenigsten signifikanten Byte des Werts gespeichert, und da die Größen nicht mit der Position übereinstimmen Dieses Byte im Speicher unterscheidet sich in den CPU- und GPU-Versionen der Struktur.
Das manuelle Einfügen des entsprechenden Auffüllens und das Sicherstellen einer korrekten 16-Byte-Ausrichtung oder die Verwendung eines Typs mit geeigneter Größe, z. B. einer Ganzzahl, sollte das Problem beheben. Dieser Thread kann auch für Sie von Nutzen sein, da er eine eingehendere Diskussion ungefähr des gleichen Problems enthält.
quelle
isTextured
Passen Sie in dasselbe Register, da es sich in das nächste überspannen müsste. Somit wird es vollständig in das nächste Register gestoßen." Das zweite Register besteht ausspecular
den ersten drei Komponenten undisTextured
der letzten, also sehe ich nicht, dass irgendetwas in das nächste Register gestoßen werden muss? Die Bool-Länge von 1 Byte gegen 4 Byte ist offensichtlich wichtig, aber beide passen danachspecular
in dasselbe Register.Okay, habe etwas gelesen und festgestellt, dass ein hlsl-Bool im Wesentlichen eine 32-Bit-Ganzzahl ist. Also habe ich einfach ein int in der c ++ - Struktur verwendet, um mein Problem zu lösen.
quelle
float, bool und int sind für endian nicht erforderlich, insbesondere für mehrere Elemente.
Das Umschalten auf int oder float funktioniert in einigen der hier aufgeführten Beispiele, da es zwischen XMFLOAT3-Elementen ausgerichtet ist und daher korrekt referenziert wird. Wenn Sie jedoch ein Array oder mehrere Elemente in der Struktur für int, float deklarieren müssen (keine XM-Typen), werden Sie wahrscheinlich feststellen, dass die GPU-Werte nicht mit den in der CPU-Struktur festgelegten Werten übereinstimmen.
Ich habe es sicherlich getan, als ich ein Array vom Typ int hinzugefügt habe, das für den Beleuchtungstyp verwendet werden soll.
Der einfachste Weg, den ich gefunden habe, besteht darin, mich an XM-Typen zu halten, die um 16 ausgerichtet sind. Dies erfordert möglicherweise verschwendete Elemente / Bytes, sortiert aber den Endian für Sie. EG XMINT4 und hat gerade das erste Element .x für Ihren Wert verwendet, oder wenn Sie die Notwendigkeit haben, verwenden Sie die anderen Elemente für einen anderen Zweck, was jedoch eine schlechte Benennung bedeutet (stellen Sie sicher, dass Sie einen Kommentar abgeben). Hinweis: Das XMINT2-Array ist ebenfalls nicht in logischer Reihenfolge
quelle