W porządku, trudno mi się spakować bool i ustawić w buforze ciągłym hlsl i nie jestem pewien dlaczego.
Oto bufor w hlsl
cbuffer MaterialBuffer : register(b1) {
float3 materialDiffuseAlbedo;
float materialSpecularExponent;
float3 materialSpecularAlbedo;
bool isTextured;
};
I tutaj jest w c ++
struct GeometryBufferPass_MaterialBuffer {
XMFLOAT3 diffuse;
float specularExponent;
XMFLOAT3 specular;
bool isTextured;
};
Próbowałem przesuwać bool i wypełniać strukturę na wiele sposobów bez powodzenia. Jaki jest właściwy sposób to zrobić?
directx
hlsl
data-structure
KlashnikovKid
źródło
źródło
Odpowiedzi:
W celu zwiększenia wydajności, stałe bufory będą odwzorowane tak, że wartości nie będą przechodzić przez rejestry GPU . Każdy rejestr ma cztery zmiennoprzecinkowe rozmiary (16 bajtów), więc stałe struktury buforów muszą być wielokrotnością ich na GPU. Struktura C ++ powinna zostać odpowiednio uzupełniona, jeśli chcesz użyć jej jako wygody do mapowania danych (ta uwaga, nie zawsze dobrze się skaluje).
Problem polega na tym, że wartość logiczna HLSL ma cztery bajty, ale jeden bajt po stronie procesora (w konkretnej implementacji). Powoduje to, że struktura C ++ nie jest odpowiednio wyrównywana: znaczący bit wartości logicznej (0 lub 1, która ma znaczenie) będzie przechowywany w najmniej znaczącym bajcie wartości, a ponieważ rozmiary nie zgadzają się z lokalizacją tego bajtu w pamięci będzie się różnić w wersjach struktury CPU i GPU.
Ręczne wstawienie odpowiedniego dopełnienia i zapewnienie prawidłowego wyrównania do 16 bajtów lub po prostu użycie odpowiedniego rozmiaru, takiego jak liczba całkowita, powinno rozwiązać problem. Ten wątek może być również przydatny, ponieważ zawiera bardziej dogłębną dyskusję na temat tego samego problemu.
źródło
isTextured
zmieści się w tym samym rejestrze, ponieważ musiałby on przechodzić do następnego. W ten sposób zostaje całkowicie zderzony z następnym rejestrem”. Drugi rejestr składa się zspecular
pierwszych trzech składników iisTextured
ostatniego, więc nie widzę, że coś trzeba wpaść na następny rejestr? Długość boola 1-bajt vs 4-bajt ma oczywiście znaczenie, ale każdy z nich zmieściłby sięspecular
w tym samym rejestrze.W porządku, przeczytałem trochę i zauważyłem, że hlsl bool jest w zasadzie 32-bitową liczbą całkowitą. Więc użyłem int w strukturze c ++, aby rozwiązać mój problem.
źródło
float, bool i int nie wymagają ustawiania w linii dla endianu, szczególnie w przypadku wielu przedmiotów.
Przełączanie na int lub float działa w niektórych przykładach wymienionych tutaj, ponieważ jest wyrównane między elementami XMFLOAT3, więc są poprawnie przywoływane. Jeśli jednak musisz zadeklarować tablicę lub kilka elementów w strukturze dla int, float (brak typów XM), prawdopodobnie przekonasz się, że wartości GPU nie pasują do wartości ustawionych w strukturze CPU.
Z pewnością zrobiłem to, dodając tablicę typu int, która będzie używana jako typ oświetlenia.
Najprostszym sposobem, jaki znalazłem, jest trzymanie się typów XM, które wyrównują się o 16, co może wymagać zmarnowanych elementów / bajtów, ale sortuje dla ciebie endian. EG XMINT4 i właśnie użył pierwszego elementu .x dla swojej wartości lub, jeśli masz taką potrzebę, użyj innych elementów w innym celu, ale oznacza to złe nazewnictwo (pamiętaj o komentarzu). Uwaga: Tablica XMINT2 również nie będzie logiczna
źródło