2

GLSL シェーダーを実行可能ファイル内に格納してきちんとしたいのですが、シェーダー オブジェクトにロードする関数内で文字列を定義すると、関数が返されたときにスタックから文字列が削除されますか? 代わりにこれを別の方法で行う必要がありますか?(リソースファイルについて何か読んだことは覚えていますが、以前にそれらを使用したことはありません)

4

2 に答える 2

2

GLSL シェーダーを実行可能ファイル内に格納して整理したいのですが、

これにはほとんど意味がありませんが、動機は理解できます。

それらをシェーダーオブジェクトにロードする関数内で文字列を定義すると、関数が戻ったときにスタックから文字列が削除されますか?

それはあなたがそれをどのように宣言するかによって異なります。次のようなものを書く場合:

void foo(…)
{
    char const string[] = "....";
}

文字列メモリはスタックに割り当てられ、初期化文字列リテラルの内容で初期化されます。文字列リテラル自体は、実行可能ファイルの定数データ セグメント内の特定の場所へのポインターです。データ セグメントは、必要に応じてプロセス アドレスにマップされます (残りの実行可能ファイル^1.

関数が戻ると、メモリは「解放」されます。技術的には、ロールバックされるのはスタック ポインターだけです。

のように書くと

void bar(...)
{
    char const * string = "....";
}

変数stringは、文字列リテラルが配置されている定数データ セグメント自体の部分へのポインターで初期化されます。メモリは割り当てられず、リテラルが存在するページが実際にアクセスされた場合にのみ、コンテンツがディスクから読み取られます。

技術的な観点から見ると、文字列リテラルにアクセスすると、データ アクセスのためにファイルを mmap するのとまったく同じ量のメモリと I/O オーバーヘッドが追加されます。実際、実行可能ファイル自体は mmap 化されているため、これはすでに mmap 化されたファイルへのアクセスです。


[1] ブロッキング syscall で長時間待機している実行可能ファイルは、最終的にシステム メモリからスワップ アウトされ、syscall が返されたときにスワップ バックされます。実際、最近の OS では、すべてのシステム メモリがブロック I/O キャッシュとして処理され、プロセス メモリの割り当てがブロック デバイスの内容として扱われます (これにより、スワップ空間の実装が簡単になります)。バッキング ブロック デバイスがないと、プロセス メモリである「キャッシュ」がスワップできなくなります。

于 2013-03-01T16:50:38.810 に答える
1

それらをシェーダーオブジェクトにロードする関数内で定義された文字列を持っていると、関数が戻ったときにスタックから文字列が削除されますか?

はい。関数がコントロールを呼び出し元に返すと、スタックは常に「ポップ」されます。

代わりにこれを別の方法で行う必要がありますか?

ファイルからロードすることをお勧めします。そうすれば、リソースを一時的に占有するだけです (つまり、ファイルを仮想メモリにマップし、これをデバイスに転送してから、ファイルのマップを解除します)。

これがオプションでない場合は、データを静的グローバル メモリに定義して、最終的にプログラムの「データ」セグメントに配置することをお勧めします。そうすれば、静的メモリとスタックの両方を占有しません(そうしないと、どこかからスタックのメモリにロードする必要があり、とにかく「データ」セグメントになる可能性が高いため)。例えば:

void load_data()
{
    static const unsigned char mydata[] = { 0x01, 0x02, ... };
    /* Do something with "mydata" */
}
于 2013-03-01T16:23:31.230 に答える