2013-02-14 22 views
6

पर मैं ओपनजीएल 2.1 के साथ Win32 थ्रेड का उपयोग करता हूं। जो मैं हासिल करने की कोशिश कर रहा हूं वह है कि "लोडिंग" कहकर सरल छवि प्रस्तुत करना है, जबकि पृष्ठभूमि में पूरे 3 डी दृश्य को लोड किया जा रहा है। यह अब काम करता है, लेकिन मुझे एक समस्या है, जहां कभी-कभी मेरे क्यूबमैप बनावट का एक हिस्सा मोज़िला फ़ायरफ़ॉक्स ब्राउज़र से डेटा लेता है (यह कैसे होता है ???) और बनावट के साथ उस छोटे बॉक्स को अनदेखा करें, यह केवल एक स्प्राइट है और यह वह जगह है जहां यह होना चाहिए .: enter image description hereओपनजीएल संसाधन लोडिंग दूसरे थ्रेड

यह 3 बार में होता है जैसे मैं अपना प्रोग्राम लोड करने का प्रयास करता हूं। यह कैसे मेरे धागा लग रहा है:

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. किसी भी विचार के बारे में नवीनतम चालकों के साथ एनवीडिया 670GTX का उपयोग जहां समस्या हो सकती है?

[संपादित करें] मैंने अपने लोडर थ्रेड के अंत में glfinish() जोड़ा, और अब सबकुछ सामान्यता लोड करता है। मैं कहीं कहीं लाल हूं, कि ओपनजीएल तुरंत इसके सभी काम खत्म नहीं करता है, इसलिए मुझे लगता है कि यह मामला था, जहां संदर्भ को पूरा करने से पहले संदर्भ को पूर्ण करने के लिए सेट किया गया था।

+1

एक नोट लें कि ओपनग्ल और थ्रेड आमतौर पर –

+0

के साथ नहीं जाते हैं, हाँ, मैं इसके बारे में काफी कुछ करता हूं। वास्तव में, मैंने पहले दो संदर्भों को लागू किया था, एक पर मैंने प्रस्तुत किया था, दूसरे पर मैंने संसाधनों को लोड किया था, और जब संसाधन लोड किए गए थे, तो मैंने अंतिम संदर्भ को हटाते हुए उस संदर्भ को लिया और इसे मुख्य संदर्भ बना दिया। यह कोई समस्या नहीं के साथ काम किया। – SMart

+0

@ BЈовић: ओपनजीएल और मल्टीथ्रेडिंग किया जा सकता है, यह सही पाने के लिए बस इतना आसान नहीं है। – datenwolf

उत्तर

7

अब यह काम करता है, लेकिन मैं (नरक में करता है यह कैसे होता ???)

आपका बनावट एक समस्या है, जहां कभी कभी मेरे cubemap बनावट का एक हिस्सा मोज़िला फ़ायरफ़ॉक्स ब्राउज़र से डेटा लेता है अनियमित ग्राफिक्स मेमोरी से डेटा प्राप्त करता है, जिसमें शायद अन्य प्रक्रिया से अवशिष्ट छवियां हो सकती हैं, जो पहले उस स्मृति क्षेत्र का उपयोग करती थीं। इस तरह सामग्री, तब हो सकता है

क) ड्राइवर एक बग है और धागे

और

ख) यदि आप एक बनावट को संशोधित करने के प्रयास कर रहे हैं के बीच संसाधनों को सिंक्रनाइज़ नहीं करता है, जबकि यह बाध्य है अन्य धागे में एक बनावट इकाई के लिए।

संपादित करें: आप उचित सिंक्रनाइज़ेशन स्वयं को (और चाहिए) पेश कर सकते हैं। बस क्योंकि यह प्रदर्शन को बढ़ाता है। जब बनावट वर्तमान में व्यस्त नहीं है, तो थ्रेड के बीच संवाद करने के लिए condition variables का उपयोग करें। आदर्श रूप से आप दो या दो से अधिक बनावट का उपयोग करते हैं, आप एक राउंड रॉबिन फैशन में अपडेट करते हैं।

+0

आपके उत्तर ने मुझे एक वास्तविक समस्या खोजने में मदद की, धन्यवाद ^^ – SMart

+0

@SMGhost: कृपया मेरा संपादन जोड़ा भी देखें। – datenwolf

+0

यदि मैं सही ढंग से समझ गया, तो आप केवल एक संदर्भ का उपयोग करने का सुझाव देते हैं, और जहां मैं इसका उपयोग करता हूं, वहां सभी सिंक्रनाइज़ करना, ताकि कोई दौड़ की स्थिति न हो? या एकाधिक संदर्भों का उपयोग कर, लेकिन अभी भी खुद को सिंक्रनाइज़ कर रहा है, तो opengl ड्राइवर को नहीं करना होगा? – SMart