QT GPU混合使用

GPU相对CPU,可以更好地并行处理数据,因此可以利用GPU,来进行可以并行的计算,比如图像处理中,若每个像素的处理都独立于其他像素,则就可以使用GPU来加速。

GPGPU的一个比较一般而通用的核心方法就是将待处理的图片或者其他数据转成比如说OpenGL的纹理,然后用OpenGL绘制一个矩形,并使用GLSL、Cg、HLSL等着色语言编写着色程序实现针对每个数据的算法,OpenGL绘制的东西放在用于离屏渲染的帧缓存对象FBO里,每个输入数据对应一组输出,运算完后从FBO中获得结果。

GPGPU的实现方法可以参考如下文章:

http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.html

翻译版:

http://blog.csdn.net/huawenguang/archive/2007/03/15/1530547.aspx

 

其中细节不多说,文章讲得比较详细,也有源码提供。下面我写一下我总结的一些问题

 

一、硬件支持

要想GPGPU有较好效果,显卡不能太烂……我之前使用一个笔记本的集成显卡,结果综合起来还没有用CPU跑的快。

对于OpenGL的纹理,较烂的显卡只能支持浮点纹理,只有Geforce8以上才能支持整型纹理。虽然似乎显卡处理浮点数速度挺快,但整型纹理的好处是,对于Qt来说,图像像素信息是以整数形式存储的,这样导入导出GPU时不需要转换。

另外,对于N卡和A卡,OpenGL纹理创建的时候的格式是有区别的,虽然也有通用的格式,不过也不是全都覆盖的,还是会有一些型号的显卡无法运行,需要使用更针对性的格式(参考文章中的相关表格)。因此,这里需要识别出当前系统的显卡型号,并以此选择不同的格式。

其他平台我不知道,Windows下,各个硬件的信息都放在了注册表里,因此我们要做的就是找到这个地方,并找到显卡的位置,然后读取相关的信息,并根据信息来设置参数

硬件信息的注册表地址:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class

  1. void SetTextureParams()  
  2. {  
  3.     SP_DEVINFO_DATA   DeviceInfoData;   
  4.     DeviceInfoData.cbSize   =   sizeof(SP_DEVINFO_DATA);   
  5.     char   buffer[MAX_PATH];   
  6.     ZeroMemory(buffer,   MAX_PATH);   
  7.     HKEY   hCurKey;   
  8.     std::string   strConstKey;   
  9.     HKEY   hRootKey   =   HKEY_LOCAL_MACHINE;   
  10.     OSVERSIONINFO osvi;  
  11.     BOOL bIsWindowsXPorLater;  
  12.     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));  
  13.     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
  14.     GetVersionEx(&osvi);  
  15.     // 获得操作系统版本  
  16.     bIsWindowsXPorLater =   
  17.         ( (osvi.dwMajorVersion > 5) ||  
  18.         ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ));  
  19.     if   (bIsWindowsXPorLater)   
  20.         strConstKey   =   "SYSTEM//CurrentControlSet//Control//Class//";   
  21.     else   
  22.         strConstKey   =   "SYSTEM//CurrentControlSet//Services//Class//";   
  23.     HDEVINFO hDevInfo;  
  24.   
  25.     // Create a HDEVINFO with all present devices.  
  26.     hDevInfo = SetupDiGetClassDevs(NULL,  
  27.         0, // Enumerator  
  28.         0,  
  29.         DIGCF_PRESENT | DIGCF_ALLCLASSES );  
  30.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  31.     {  
  32.         // Insert error handling here.  
  33.         return;  
  34.     }  
  35.     char szValueData[100];  
  36.     DWORD dwVDataSize=100;  
  37.     for   (DWORD   i=0;SetupDiEnumDeviceInfo(hDevInfo,i,&DeviceInfoData);i++)   
  38.     {   
  39.         SetupDiGetDeviceRegistryPropertyA(hDevInfo,   &DeviceInfoData,     
  40.             SPDRP_DRIVER,   NULL,   (PBYTE)buffer,   MAX_PATH,   NULL);   
  41.         std::string   strKey   =   strConstKey;   
  42.         strKey.append(buffer);   
  43.         char dpath[100]={0}, purepath[100]={0};  
  44.         int strlength=strlen(strKey.c_str());  
  45.         memcpy(dpath, strKey.c_str(), strlength+1);  
  46.         if(dpath[strlength-1]!='}'){  
  47.             int temp=strcspn(dpath, "}");  
  48.             memcpy(purepath, dpath, temp+1);  
  49.         }  
  50.         else{  
  51.             memcpy(purepath, dpath, strlength+1);  
  52.         }  
  53.         if   (ERROR_SUCCESS   !=   ::RegOpenKeyExA(hRootKey,   (LPCSTR)purepath, 0, KEY_READ,  &hCurKey))   
  54.         {   
  55.             //      TRACE( "%d ",   GetLastError());   
  56.             return;   
  57.         }   
  58.         //   Get   the   driver   description   
  59.         DWORD   dwType   =   REG_SZ;   
  60.         // 根据Class的名称,找到显卡的对应项,即Display  
  61.         if   (ERROR_SUCCESS   ==   ::RegQueryValueExA(hCurKey,   (LPCSTR)"Class",   NULL,   &dwType,   (LPBYTE)szValueData,   &dwVDataSize)) {  
  62.             dwVDataSize=100;  
  63.             if(strcmp((char*)szValueData, "Display")!=0){  
  64.                 continue;  
  65.             }  
  66.             if   (ERROR_SUCCESS   !=   ::RegOpenKeyExA(hRootKey,   (LPCSTR)dpath, 0, KEY_READ,  &hCurKey)){  
  67.                 return;  
  68.             }  
  69.             // 找到显卡后,我这里是简单地根据厂商,即ProviderName来判断;DriverDesc提供了具体的型号描述,也可发掘其他有用信息  
  70.             if   (ERROR_SUCCESS   ==   ::RegQueryValueExA(hCurKey,   (LPCSTR)"ProviderName",   NULL,   &dwType,   (LPBYTE)szValueData,   &dwVDataSize)) {  
  71.                 dwVDataSize=100;  
  72.                 if(strcmp((char*)szValueData, "NVIDIA")==0){  
  73.                     // 设置N卡的参数  
  74.                 }  
  75.                 else{  
  76.                     // 设置其他卡的参数  
  77.                 }  
  78.                 return;  
  79.             }  
  80.         }  
  81.     }  
  82. }  

参考文献:http://topic.csdn.net/t/20051027/13/4353990.html

 

二、纹理坐标

OpenGL的纹理有两种tex2D和texRect。前者必须是正方形纹理,纹理坐标范围为[0, 1];后者可以是任意形状,纹理坐标范围为[0.5, length-0.5],而不是[0, length-1]。

 

三、GLSL

GLSL的输出颜色变量:gl_FragColor

这个变量似乎不能读,只能写。如果先对它赋值,然后再读取它,在很多情况下会编译不通过。我之前写了个简单的程序没啥问题。后来程序里加了个循环语句,就死也编译不了了。因此,gl_FragColor最好在程序的最后赋值,如果需要对输出结果反复修改,先放在一个临时变量里。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值