LoginSignup
4
7

More than 5 years have passed since last update.

DirectX9とC++11のマルチスレッドを使用して裏画面ロードを実装する話

Last updated at Posted at 2016-12-09

今回作るもの

裏で処理しながらローディング画面を出す

なぜDirectX"9"なのか。

「課題要件」です

環境

Visual Studio 2015
DirectX SDK (June 2010)
Intel® Core™ i7-4810MQ

準備

まずはThreadが使用できなければ始まりません。
スレッド数はstd::thread::hardware_concurrency()で確認できます。
快適なデバックを行うにはmain+VisualStudio+osで3スレッド必要です。
今回専有しないので考慮しませんが、スレッドを専有する場合はosなどの他のプログラムを考慮する必要があります。

main.cpp
auto count = std::thread::hardware_concurrency();
if (count < 3)
{
    //Err
}

裏処理

マルチスレッドで処理を行う場合、複数スレッドに跨るデータをスレッドセーフにする必要があります。
今回だとロードの終了を通知するフラグを、スレッドセーフに扱う関数を定義します。

main.cpp
bool isLoaded = false;
std::mutex isLoadedMutex;

void SetLockFlag(bool _)
{
    std::lock_guard<std::mutex>  lock(isLoadedMutex);
    isLoaded = true;
}

bool GetLockFlag()
{
    std::lock_guard<std::mutex>  lock(isLoadedMutex);
    return isLoaded;
}

void AsyncLoad()
{
    //ダミーで10秒待つ
    auto sleepTime = std::chrono::seconds(10);
    std::this_thread::sleep_for(sleepTime);

    SetLockFlag(true);
}

Thread起動

このステートメントを実行すると同時に非同期関数が起動します。

main.cpp
std::thread th(AsyncLoad);

完了通知

main.cpp

if (!GetLockFlag())
{
    //ロード中
}
else
{
    //ロード完了
}

後始末

Threadはそのデストラクタが呼ばれる前に、joinまたはdetachを呼ぶ必要があります。
今回はjoinを行いスレッドが終了するのを待機していますが、detachにすると
Threadのデストラクタ後も関数が走り続けます。

main.cpp
th.join();

注意点

・データ競合
データの書き込みと読み込みが同時に行われると発生します。
運が良ければどこかでクラッシュとして拾われますが、悪ければ顕著化せずに埋もれてしまい探し出すのに非常に労力を要します。

・DirectX9のデバイスについて
残念ですが、DirectX9のデバイスはスレッドセーフではありません。
そのため、レンダリングしながら裏で(デバイスを使用した)ロードと言うのは不可能です。

参考文献

・DirectXのデバイスのスレッドセーフ性について:
https://msdn.microsoft.com/ja-jp/library/ee422106(v=vs.85).aspx
・データ競合:
http://yohhoy.hatenablog.jp/entry/2013/12/15/204116
・C++11のスレッド:
http://www.slideshare.net/hotwatermorning/c-38563753

今回のプロジェクト

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7