GLSL シェーダーを実行可能ファイル内に格納してきちんとしたいのですが、シェーダー オブジェクトにロードする関数内で文字列を定義すると、関数が返されたときにスタックから文字列が削除されますか? 代わりにこれを別の方法で行う必要がありますか?(リソースファイルについて何か読んだことは覚えていますが、以前にそれらを使用したことはありません)
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 キャッシュとして処理され、プロセス メモリの割り当てがブロック デバイスの内容として扱われます (これにより、スワップ空間の実装が簡単になります)。バッキング ブロック デバイスがないと、プロセス メモリである「キャッシュ」がスワップできなくなります。
それらをシェーダーオブジェクトにロードする関数内で定義された文字列を持っていると、関数が戻ったときにスタックから文字列が削除されますか?
はい。関数がコントロールを呼び出し元に返すと、スタックは常に「ポップ」されます。
代わりにこれを別の方法で行う必要がありますか?
ファイルからロードすることをお勧めします。そうすれば、リソースを一時的に占有するだけです (つまり、ファイルを仮想メモリにマップし、これをデバイスに転送してから、ファイルのマップを解除します)。
これがオプションでない場合は、データを静的グローバル メモリに定義して、最終的にプログラムの「データ」セグメントに配置することをお勧めします。そうすれば、静的メモリとスタックの両方を占有しません(そうしないと、どこかからスタックのメモリにロードする必要があり、とにかく「データ」セグメントになる可能性が高いため)。例えば:
void load_data()
{
static const unsigned char mydata[] = { 0x01, 0x02, ... };
/* Do something with "mydata" */
}