異なるシェーダーステージで異なるプッシュ定数を使用する 質問する

異なるシェーダーステージで異なるプッシュ定数を使用する 質問する

1 つの float を含む push-constant ブロックを持つ頂点シェーダーがあります。

layout(push_constant) uniform pushConstants {
    float test1;
} u_pushConstants;

異なる float 値を持つ別の push-constant ブロックを持つフラグメント シェーダー:

layout(push_constant) uniform pushConstants {
    float test2;
} u_pushConstants;

テスト1そしてテスト2違うはずです。

パイプライン レイアウトのプッシュ定数範囲は次のように定義されます。

std::array<vk::PushConstantRange,2> ranges = {
    vk::PushConstantRange{
        vk::ShaderStageFlagBits::eVertex,
        0,
        sizeof(float)
    },
    vk::PushConstantRange{
        vk::ShaderStageFlagBits::eFragment,
        sizeof(float), // Push-constant range offset (Start after vertex push constants)
        sizeof(float)
    }
};

実際の定数は、次のようにレンダリング中にプッシュされます。

std::array<float,1> constants = {123.f};
commandBufferDraw.pushConstants(
    pipelineLayout,
    vk::ShaderStageFlagBits::eVertex,
    0,
    sizeof(float),
    constants.data()
);
std::array<float,1> constants = {456.f};
commandBufferDraw.pushConstants(
    pipelineLayout,
    vk::ShaderStageFlagBits::eFragment,
    sizeof(float), // Offset in bytes
    sizeof(float),
    constants.data()
);

しかし、シェーダー内の値を確認すると、両方とも 123 になっています。オフセットは完全に無視されているようです。使い方が間違っているのでしょうか?

ベストアンサー1

パイプライン レイアウトでは、頂点シェーダーがプッシュ定数範囲内の [0, 4) バイトのデータ範囲にアクセスすると述べました。フラグメント シェーダーがプッシュ定数範囲内の [4, 8) のデータ範囲にアクセスすると述べました。

しかし、あなたのシェーダーは別の物語を語っています。

layout(push_constant) uniform pushConstants {
    float test2;
} u_pushConstants;

この定義では、プッシュ定数範囲の開始が [0, 4) であると明確に述べています。しかし、Vulkan には [4, 8) を使用すると伝えています。Vulkan は、シェーダーとパイプライン レイアウトのどちらを信じるべきでしょうか?

覚えておくべき一般的なルールは、シェーダーはそれが意味する通りの意味を持つということです。パイプライン作成時に与えられたパラメータは変化コードの意味。

フラグメントシェーダが実際に[4, 8)を使用するようにしたい場合は、フラグメントシェーダは実際に使ってみる:

layout(push_constant) uniform fragmentPushConstants {
    layout(offset = 4) float test2;
} u_pushConstants;

VSバージョンとは定義が異なるため、ブロック名も異なります。offsetレイアウトは問題の変数のオフセットを指定します。これはGLSLの標準的なもので、Vulkan 用にコンパイルするそれは変わりません。

おすすめ記事