2013-02-14 8 views
6

OpenGL 2.1でwin32スレッドを使用します。私が達成しようとしているのは、「ロード中」という単純なイメージをレンダリングし、バックグラウンド全体で3Dシーンがロードされていることです。今は動作しますが、時には私のキューブマップのテクスチャの一部がMozilla Firefox Browserからデータを取得する問題があります(これはどのように起こりますか?)、その小さなボックスはテクスチャで無視します。それはそれがあるはずです。: enter image description here2番目のスレッドでのOpenGLリソースのロード

私はプログラムをロードしようとします。 は、これは私のスレッドがどのように見えるかです:

WindowsThread::WindowsThread(HGLRC graphicsContext, HDC deviceContext) : 
    graphicsContext_(graphicsContext), 
    deviceContext_(deviceContext), 
    running_(false), 
    task_(0), 
    mode_(WT_NORMAL) 
{ 
    handle_ = CreateThread(0, 0, 
     (unsigned long (__stdcall *)(void *)) this->staticRun, 
     (void*) this, CREATE_SUSPENDED, &id_); 

    if (handle_ == 0) { 
     LOGE("Unable to create thread."); 
     return; 
    } 

    if (!SetThreadPriority(handle_, THREAD_PRIORITY_NORMAL)) { 
     LOGE("Unable to set thread priority for thread."); 
     return; 
    } 
} 

WindowsThread::~WindowsThread() { 
    finishTask(); 
    running_ = false; 
    WaitForSingleObject(handle_, INFINITE); 
    CloseHandle(handle_); 
    wglDeleteContext(graphicsContext_); 
} 

void WindowsThread::start() { 
    running_ = true; 
    if (!ResumeThread(handle_)) { 
     LOGW("Unable to resume thread."); 
    } 
} 

bool WindowsThread::isRunning() { 
    return running_; 
} 

void WindowsThread::setTask(Task* task, Mode mode) { 
    finishTask(); 
    task_ = task; 
    mode_ = mode; 
} 

bool WindowsThread::hasTask() { 
    return task_ != 0; 
} 

void WindowsThread::finishTask() { 
    while (task_ != 0) { 
     Sleep(1); 
    } 
} 

void WindowsThread::stop() { 
    running_ = false; 
} 

int WindowsThread::staticRun(void* thread) { 
    return ((WindowsThread*) thread)->run(); 
} 

int WindowsThread::run() { 
    wglMakeCurrent(deviceContext_, graphicsContext_); 
    while (running_) { 
     if (task_ != 0) { 
      task_->run(); 
      task_ = 0; 
     } 
     Sleep(10); 
    } 
    wglMakeCurrent(0, 0); 
    return 1; 
} 

ThreadManager:

WindowsThreadManager::WindowsThreadManager(
    System* system, UINT threadPoolSize) 
{ 
    if (threadPoolSize == 0) { 
     SYSTEM_INFO info; 
     GetSystemInfo(&info); 
     threadPoolSize = info.dwNumberOfProcessors; 
     if (threadPoolSize == 0) { 
      threadPoolSize = 1; 
     } 
    } 
    LOGI("Number of threads used: %d", threadPoolSize); 
    masterContext_ = wglGetCurrentContext(); 
    HDC hdc = wglGetCurrentDC(); 
    for (UINT i = 0; i < threadPoolSize; i++) { 
     HGLRC threadContext = wglCreateContext(hdc); 
     wglShareLists(masterContext_, threadContext); 
     WindowsThread* thread = new WindowsThread(threadContext, hdc); 
     thread->start(); 
     threads_.push_back(thread); 
    } 
} 

WindowsThreadManager::~WindowsThreadManager() { 
    for (UINT i = 0; i < threads_.size(); i++) { 
     delete threads_[i]; 
    } 
    for (UINT i = 0; i < tasks_.size(); i++) { 
     delete tasks_[i]; 
    } 
} 

void WindowsThreadManager::execute(Task* task, Mode mode) { 
    WindowsThread::Mode wtMode = WindowsThread::WT_NORMAL; 
    if (mode == TM_GRAPHICS_CONTEXT) { 
     wtMode = WindowsThread::WT_GRPAHICS_CONTEXT; 
    } 
    tasks_.push_back(task); 
    for (UINT i = 0; i < threads_.size(); i++) { 
     if (!threads_[i]->hasTask()) { 
      threads_[i]->setTask(task, wtMode); 
      return; 
     } 
    } 
    threads_[0]->setTask(task, wtMode); 
} 

void WindowsThreadManager::joinAll() { 
    for (UINT i = 0; i < threads_.size(); i++) { 
     if (threads_[i]->hasTask()) { 
      threads_[i]->finishTask(); 
     } 
    } 
} 

私はWinodws 8 上の最新のドライバに問題があるかもしれない任意のアイデアとNvidiaの670GTXを使うのか?

[編集]ローダースレッドの最後にglFinish()を追加しました。これですべて正常にロードされます。私はどこかで赤く、OpenGLはすぐにそのすべての作業を終了しないので、これは事実だと思います。コンテキストがNULLに設定されて作業を完了することができました。

+1

openglとスレッドは通常通りません。 –

+0

はい、私はそれについてかなり赤いです。実際には、前に2つのコンテキストを実装していました.1つはレンダリングしたものに、もう1つはリソースをロードしました。リソースがロードされたときに、私はそのコンテキストを取り、それをメインコンテキストとし、最後のメインコンテキストを削除しました。これは問題なく動作しました。 – SMart

+0

@BЈовић:OpenGLとマルチスレッドができますが、それは正しいことが簡単ではありません。 – datenwolf

答えて

7

それが機能するようになりましたが、私は時々私のキューブマップテクスチャの一部は、Mozilla Firefoxのブラウザからデータを受け取り、問題、(どのように地獄では、これは???起こるん)

あなたの質感を持っていますそのメモリ領域を以前に使用した、他のプロセスからの残存画像を含む可能性が高い初期化されていないグラフィックスメモリからデータを受け取る。このようなものは、発生する可能性があれば

a)のドライバはバグがあり、それがバインドされたのですが、あなたはテクスチャを変更しようとしている場合、スレッド

b)の間でリソースを同期しません。他方のスレッドのテクスチャユニットに送る。

編集:あなたは自分自身で適切な同期を導入することができます。パフォーマンスが向上するからです。テクスチャが現在ビジー状態でない場合は、condition variablesを使用してスレッド間の通信を行います。理想的には、2つ以上のテクスチャを使用し、ラウンドロビン方式で更新します。

+0

あなたの答えは本当に問題を見つけるのを助けました^^ – SMart

+0

@SMGhost:私の編集も見てください。 – datenwolf

+0

私が正しく理解していれば、1つのコンテキストのみを使用し、使用する場所すべてを同期させることで、競合条件がないようにすることをお勧めしますか?または複数のコンテキストを使用して、それでも自分自身を同期させるので、OpenGLドライバは必要ありませんか? – SMart

関連する問題