OpenGL多线程

首先使用同一个DC创建两个RC,并且使用wglShareLists共享两个RC的资源。建议不要给这三个函数之间加其他向RC中添加东西的GL函数。

HGLRC hRC1 = wglCreateContext(hDC);

HGLRC hRC2 = wglCreateContext(hDC);

wglShareLists(hRC2, hRC1);

注意:wglShareLists的第一个参数中的RC是分享别人资源的,第二个参数中的RC是奉献资源供别人分享的。

 

//这是一个用来渲染场景的线程(也可用主线程来渲染)

renderingThread()

{

   //...

   wglMakeCurrent(hDC, hRC1);

   //...

}

理论上来讲,可以在多创建几个RC,然后用多线程同时渲染。但是据说这样做是可行但却无益的。因为OpenGL会进行一些频繁的切换,导致产生高昂的开销。

 

//这是一个用来加载资源的线程,可以加载图片,并使用创建纹理,设置纹理参数等。

loadingThread()

{

   //...

   wglMakeCurrent(hDC, hRC2);

   //...

}

注意,加载工作也可以写在多个线程中,例如使用多个线程从硬盘中读取图片文件(在多核机器上用双核读图片会比单核快一些),然后使用一个专门的线程调用GL的函数来创建纹理。但是,如果使用一些开源的图像库来读取图片的话就要注意了,有些开源的图像库不支持多线程,如DevIL。(FreeImage记得也存在这个问题)

 

最后别忘了在各个线程结束时调用wglMakeCurrent(NULL, NULL);取消DC与RC的关联。

还有要删除RC

wglDeleteContext(hRC2);

wglDeleteContext(hRC1);

 

最后要发一下牢骚。网上三维图形方面的资料相比其他计算机技术而言实在是不多,而且大多数还没有用。国内更是少的可怜,可能高人们都在忙着为买房子而奋斗导致没时间上网了。以下是该英文文章作者的感言,深有同感啊,向这种有国际主义精神的高人致敬。

It was quite a struggle to find anything useful in the web, only some minor things at few forums and mailing groups. But using that with some thinking and reading between lines I finally found the solution I’d like to share, as it can save (in my opinion) much time of searching and experimenting for others.

 

  

 

 

 

 

 

It is possible to create multiple threads in an OpenGL application and have each thread call OpenGL functions to draw an image. You might want to do this when multiple objects need to be drawn at the same time or when you want to have certain threads perform the rendering of specific types of objects.

This article explains how to obtain GLTHREAD, a sample that demonstrates how to implement multiple threads in an OpenGL application. The main process default thread creates two threads that each draw a three-dimensional wave on the main window. The first thread draws a wave on the left side of the screen. The second thread draws a wave on the right side of the screen. Both objects are drawn simultaneously, demonstrating OpenGL's ability to handle multiple threads.

MORE INFORMATION
The following file is available for download from the Microsoft Download Center:...

The following file is available for download from the Microsoft Download Center:
Glthread.exe (http://download.microsoft.com/download/platformsdk/sample26/1/n351/en-us/glthread.exe)
For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591  (http://support.microsoft.com/kb/119591/EN-US/ ) How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file. When implementing multiple threads in any type of application, it is important to have adequate communication between threads. In OpenGL, it is important for two threads to know what the other thread is doing. For example, it is common practice to clear the display window before drawing an OpenGL scene. If both threads are called to draw portions of a scene and they both try to call glClear before drawing, one thread's object may get erased by another thread's call to glClear.

The GLTHREAD sample assigns the glClear function to a single thread, and ensures that the other thread does not perform any drawing until glClear has been called. When a menu command message is sent to the main window, the application calls CreateThread twice to create two threads. Each thread calls GetDC(hwndMain) to obtain its own device context to the main window.

Then, each thread calls GLTHREAD's bSetupPixelFormat function to set up the pixel format and calls wglCreateContext to create a new OpenGL Rendering Context. Now, each thread has its own Rendering Context and both can call wglMakeCurrent to make its new OpenGL rendering context its (the calling thread's) current rendering context.

All subsequent OpenGL calls made by the thread are drawn on the device identified by the HDC returned from each thread's call to GetDC(). Now, because only one thread should call glClear, GLTHREAD has thread number one call it. The second thread is created "suspended" so it does nothing until a call to ResumeThread is made. After thread one has called glClear, it enables thread two to resume by calling ResumeThread with a handle to the second thread.

The procedure in the main thread that created the two other threads waits until both threads are finished before returning from the processing of the menu command message that is sent when the user selects the "Draw Waves" menu selection from the "Test Threads" menu. It will use the WaitForMultipleObjects function to do this.

 

 

 

You'll have the best chance of success with multithreading if you design your program with threading in mind. It's difficult, and often risky, to retrofit an existing OpenGL application to use multiple threads. Before you write any threading code, choose a strategy for dividing work among threads.

Consider using one of the following strategies for your OpenGL application:

  • Move OpenGL onto a separate thread.

  • Split OpenGL texture and vertex processing onto separate threads. You gain performance advantages by applying threads on single processor machines but threads are most efficient on computers with multiple CPUs since each processor can devote itself to a thread, potentially doubling the throughput.

  • For contexts on separate threads, share surfaces or OpenGL object state: display lists, textures, vertex and fragment programs, vertex array objects, and so on.

Applications that move OpenGL onto a separate thread are designed as shown in Figure 11-1. The CPU writes its data to a shared space, accessible to OpenGL. This design provides a clear division of labor and is fairly straightforward to implement. You can use this design to load data into your application on one thread, and then draw with the data on the other thread.

 

Figure 11-1  CPU processing and OpenGL on separate threads

CPU processing and OpenGL on separate threads

 

The Apple-specific OpenGL APIs provide the option for sharing data between contexts. You can leverage this feature in a threaded application by creating a separate thread for each of the contexts that share data, as shown in Figure 11-2. Shared resources are automatically set up as mutual exclusion (mutex) objects. Notice that Thread 2 draws to a pixel buffer that is linked to the shared state as a texture. Thread 1 can then draw using that texture.

 

Figure 11-2  Two contexts on separate threads

Vertex and texture processing on separate threads
 

Follow these guidelines to ensure successful threading in an application that uses OpenGL:

  • Use only one thread per context. OpenGL commands for a specific context are not reentrant. You should never have more than one thread accessing a single context simultaneously.

    If for some reason you decide to set more than one thread to target the same context, then you must synchronize threads by placing a mutex around all OpenGL calls to the context, such as gl* and CGL*. You can use one of the APIs listed in “Threading APIs” to set up a mutex. OpenGL commands that block—such as fence commands—do not synchronize threads.

  • Contexts that are on different threads can share object resources. For example, it is acceptable for one context in one thread to modify a texture and a second context in a second thread to modify the same texture. Why? Because the shared object handling provided by the Apple APIs automatically protects against thread errors. And, your application is following the "one thread per context" guideline.

  • When you use an NSOpenGLView object with OpenGL calls that are issued from a thread other than the main one, you must set up mutex locking. Why? Unless you override the default behavior, the main thread may need to communicate with the view for such things as resizing.

    Applications that use Objective-C with multithreading can lock contexts using the functions CGLLockContext and CGLUnlockContext, which were introduced in Mac OS X v10.4. If you want to perform rendering in a thread other than the main one, you can lock the context that you want to access and safely execute OpenGL commands. The locking calls must be placed around all of your OpenGL calls in all threads. You can't set up your own mutex in versions of Mac OS X earlier than v10.4.

    CGLLockContext blocks the thread it is on until all other threads have unlocked the same context using the function CGLUnlockContext. You can use CGLLockContext recursively. Context-specific CGL calls by themselves do not require locking, but you can guarantee serial processing for a group of calls by surrounding them with CGLLockContext and CGLUnlockContext. Keep in mind that calls from the OpenGL API (the API provided by the Architecture Review Board) require locking.

  • Keep track of the current context. When switching threads it is easy to switch contexts inadvertently, which causes unforeseen effects on the execution of graphic commands. You must set a current context when switching to a newly created thread.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值