5

VC++ 14.0 (2015) コンパイラのバグから学んだばかりですか? 構造体のレイアウトがメモリ内でどのようになるかについて、仮定をするべきではありません。ただし、私が見た多くのコードでそれがどのように一般的であるかがわかりません。たとえば、Vulkan グラフィックス API は次のことを行います。

構造体を定義します

struct {
    glm::mat4 projection;
    glm::mat4 model;
    glm::vec4 lightPos;
} uboVS;

次に、そのフィールドに入力します。

    uboVS.model = ...
    uboVS....

次に、構造体 (ホスト メモリ内) を memcpy 経由でデバイス メモリにコピーします。

    uint8_t *pData;
    vkMapMemory(device, memory, 0, sizeof(uboVS), 0, (void **)&pData);
    memcpy(pData, &uboVS, sizeof(uboVS));
    vkUnmapMemory(device, memory);

次に GPU に渡って、その構造体に一致するように UBO を定義します。

layout (binding = 0) uniform UBO 
{
    mat4 projection;
    mat4 model;
    vec4 lightPos;
} ubo;

次に、GPU 側では、ubo は常に uboVS と一致します。

これは同じ未定義の動作ですか?そのコードは、uboVS 構造体が定義どおりに正確にレイアウトされることに依存していないか、または両側 (コンパイルされた C++ コードとコンパイルされた SPIR-V シェーダー) が基本的に同じ異なる構造体レイアウトを生成することに依存していませんか? ( https://www.securecoding.cert.org/confluence/display/c/EXP11-C.+Do+not+make+asssumptions+regarding+the+layout+of+structures+with+の最初の例に似ていますビットフィールド)

この質問は、Vulkan やグラフィックス API に固有のものではありません。正確に何を想定できるのか、構造体をメモリのチャンクとして使用してもよいのはいつなのか、興味があります。構造体のパッキングと配置は理解していますが、それ以上のことはありますか?

ありがとう

4

3 に答える 3

5

大まかに言えば、C++ 標準がクラス メンバーの特定の内部レイアウトを義務付けていないことは事実です。

ただし、特定のオペレーティング システム用のグラフィックス ライブラリなどの専用ライブラリは、オペレーティング システム固有のコンパイラをターゲットにする予定です。彼らは、この特定のコンパイラが C/C++ クラスと構造体のメンバーのレイアウトをどのように調整するかを知っており、ライブラリは問題の実際のハードウェアに一致する適切な定義を提供します。

複数のコンパイラを持つオペレーティング システムには、多くの場合、そのオペレーティング システムのバイナリ ABI の正式な仕様があり、コンパイラはその ABI に従い、専用ライブラリはそれと同期するクラスと構造の定義を提供します。

したがって、特定のケースでは、コンパイラのドキュメントを参照して、コンパイラが構造体またはクラスのメンバーをどのようにレイアウトするかを判断した後、「構造体をメモリのチャンクとして使用してもよいと想定し、いつ使用できるか」を確認できます。それに応じて構造レイアウトを作成します。

于 2016-08-30T02:43:11.367 に答える
0

Spir-V (vulkan に渡すシェーディング言語) では、UniformConstant、Uniform、および PushConstant 変数に使用される構造体メンバーにレイアウト装飾を追加する必要があります。これを使用して、spir-V メンバー オフセットを C++ 構造体のメンバー オフセットと一致させることができます。

実際にこれを行うには、spir-V コードを検査し、必要に応じてオフセットを設定する必要があるため、注意が必要です。

于 2016-08-30T09:14:18.137 に答える