ブール値をパックしてD3D定数バッファーに配置できないのはなぜですか?


9

了解しました。ブール値をパックしてhlsl定数バッファーに配置するのに苦労しています。その理由はわかりません。

これはhlslのバッファです

cbuffer MaterialBuffer : register(b1) {
    float3 materialDiffuseAlbedo;
    float  materialSpecularExponent;
    float3 materialSpecularAlbedo;
    bool isTextured;
};

そして、ここはC ++です

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    bool isTextured;
};

私は運が悪いので、ブールを移動し、構造体にさまざまな方法でパディングしました。これを行う正しい方法は何ですか?


それが引き起こしている問題は何ですか?
MichaelHouse

boolは、シェーダーがテクスチャをサンプリングする必要があるかどうかを決定するために使用されます。このようにして、同じシェーダーでテクスチャ付きオブジェクトとテクスチャなしオブジェクトをレンダリングできます。boolは単に条件付きステートメントで使用されます。すべてのオブジェクトを同じように処理しているため、正しいデータを取得していません。現時点で空の球体だけがテクスチャを持つため、これは正しくありません。
KlashnikovKid

他の値は機能しますがブール値は機能しませんか?シェーダーで使用できるデバッガーの1つを使用して、何がそれに入れられるかを確認しましたか?
MichaelHouse

2
bool値をcharに格納してみてください。trueの場合は1、falseの場合は0として保存します。テストのためだけでなく、b ++はとにかくC ++では1バイトです
Gustavo Maciel

3
boolのサイズは実装に依存します。一部のプラットフォームでは、intと同じサイズです。 stackoverflow.com/questions/5067492/...
テトラッド

回答:


9

効率を上げるために、定数バッファは、値がGPUレジスタをまたがらないようにマッピングされます。各レジスターのサイズは4つの浮動小数点数(16バイト)であるため、GPUでは定数バッファー構造はその倍数でなければなりません。C ++構造は、データをマッピングするための便宜として使用したい場合は、それに応じてパディングする必要があります(これは、必ずしも適切にスケーリングされるとは限りません)。

したがって、あなたの問題は、HLSLブール値が4バイトですが、CPU側では(特定の実装では)1バイトであることです。これにより、C ++構造が正しく整列しなくなります。ブール値の重要なビット(重要な0または1)は、値の最下位バイトに格納されます。サイズが場所と一致しないためです。メモリ内のそのバイトのサイズは、構造のCPUとGPUバージョンで異なります。

手動で適切なパディングを挿入し、適切な16バイトアラインメントを確保するか、整数などの適切なサイズのタイプを使用するだけで問題が解決します。このスレッドは、ほぼ同じ問題に関するより詳細な説明が含まれているため、役立つかもしれません。


1
私は従いません:「次のisTexturedレジスタにまたがる必要があるため、同じレジスタに適合します。したがって、次のレジスタに完全にぶつかります。」2番目のレジスタはspecular最初の3つのコンポーネントとisTextured最後のコンポーネントで構成されているので、次のレジスタにぶつかる必要があると思いませんか?1バイトと4バイトのブール長は明らかに重要ですが、どちらもspecular同じレジスターに収まります。
Nathan Reed、

あなたは正しいです; レジスタのサイズとタイプのサイズを混同して、マッピングの表現が正しくないことに気づきました。唯一の問題は、メモリ内の関連するバイトの場所です。私はそれに応じて私の答えを調整しました。

徹底的に答えを受け入れる。あなたが言ったように、それはビッグ/リトルエンディアンの問題であり、intを使用することで解決しました。
KlashnikovKid 2012年

3

了解しました。いくつか読んで、hlsl boolは基本的に32ビット整数であることに気付きました。したがって、私は問題を解決するためにc ++構造体でintを使用しました。

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    int isTextured;
};

bool型を保持せず、コンパイラ側でintを使用しないのはなぜですか?セマンティクスを保持するだけです。
Gustavo Maciel 2012年

ええ、それは私が上記でやっていることです。struct cpu側に整数を使用し、定数バッファーgpu側にboolを使用しました。
KlashnikovKid 2012年

0

float、bool、intは、特に複数の項目の場合、エンディアンに合わせる必要はありません。

intまたはfloatへの切り替えは、XMFLOAT3アイテム間で整列されるため、ここにリストされているいくつかの例で機能し、正しく参照されます。ただし、intまたはfloat(XMタイプなし)の構造で配列または複数の項目を宣言する必要がある場合、GPU値がCPU構造のセットの値と一致しない可能性があります。

ライティングタイプに使用するintタイプの配列を追加するときに、確かにそうしました。

私が見つけた最も簡単な方法は、16で整列するXMタイプに固執することです。これは、無駄な要素/バイトを必要とする可能性がありますが、エンディアンをソートします。EG XMINT4と最初の要素.xを値に使用した場合、または必要に応じて他の要素を別の目的に使用したが、不適切な命名を意味する(必ずコメントしてください)。注:XMINT2配列も論理的な順序から外れます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.