天天看點

DX11 HLSL結構體包裝規則

從直覺上來說,我們希望在c++和在shader的cbuffer中定義的資料結構能完全對應,但由于硬體、性能等各方面的考慮,在c++和HLSL中的資料包裝規則是不一樣的,如果不注意這一點,程式可能不會報錯,但是因為資料沒有被正确的傳遞和使用,将可能發生一些很難發現的錯誤。

在HLSL中,結構體中元素的包裝規則為:

1、元素會被包裝到float4;

2、一個元素不能被分散到兩個float4中;

這兩條規則就說明了,結構體中一個字段少于float4的位元組時,何時會用empty填充,何時會用它後面的字段填充。

如果後面的字段可以完全的被目前字段剩餘空間容納,它們就會被包裝進一個float4中,否則的話,目前字段的剩餘空間将用empty填充。

對于數組類型的字段則不然,數組的每個元素都會被包裝進一個單獨的float4中,不會有多個元素整合在一起的情況。這個情況實際上造成了很多的空間浪費。例如float2 array[8]将會變成float4 array[8]。

但是我們可以在shader中通過強制類型轉換和位址計算來解決這個問題。

例如:在c++端,我們的資料為float2 array[8],那麼hlsl中我們為了順應包裝規則,可以定義為float4 array[4],它倆的記憶體大小是一樣的,資料可以完整的傳遞過去。然後再轉換類型重新解釋資料:

static float2 aggressivePackArray[8] = (float2[8])array;

這樣我們就拿到了正确的資料,并且沒有空間浪費。

是以,我們要做的就是調整字段的排列順序和良好的設計資料結構,盡量減少empty填充浪費空間,并充分了解包裝規則,從float4中取出正确的資料使用。

繼續閱讀