多线程中CUDA与opengl交互的问题

minwu222 2010-12-08 04:16:28
我建了一个opengl的CStatic如下:
头文件
OpenGLStatic.h
class OpenGLStatic : public CStatic
{
DECLARE_DYNAMIC(OpenGLStatic)

public:
OpenGLStatic();
virtual ~OpenGLStatic();

protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnPaint();
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
public:
bool Create(HWND hWnd);
void RenderScence();
bool SetWindowPixelFormat(HDC hDC);

HGLRC m_hGLContext;
HGLRC m_hGLContextShareing;
HDC m_hDC;
int m_width;
int m_height;
protected:
bool CreateViewGLContext(HDC hDC);
int m_GLPixelIndex;


int m_imageWith;
int m_imageHeight;

uchar4 *m_dResult;
cudaArray* cu_imageArray;


public:
GLuint m_pbo;
GLuint m_texid;

void SetPBOAndTexture(int width, int height);
bool SetGPUImageData(uchar4* inputImageData);
};


实现文件:

#include "OpenGLStatic.h"
#include "stdafx.h"
#include "OpenGLStatic.h"
#include <gl\GL.h>
//#include "wglext.h"

//extern "C" void initTexture(int width, int height, unsigned char*& d_in, uchar4*& uchar4_d_in, cudaArray*& cu_imageArray);
//extern "C" void uchar1_To_uchar4(IplImage*& src, unsigned char*& d_in, uchar4*& uchar4_d_in,int width, int height );
//extern "C" void cylinderProjectionKernel(uchar4* uchar4_d_in, uchar4* d_out, cudaArray* cu_imageArray, int width, int height, float f);

// OpenGLStatic
IMPLEMENT_DYNAMIC(OpenGLStatic, CStatic)

OpenGLStatic::OpenGLStatic()
: m_GLPixelIndex(0)
{
m_hGLContext = NULL;
m_hGLContextShareing = NULL;
m_hDC = NULL;

m_GLPixelIndex = 0;
m_pbo = 0;
m_texid = 0;
m_dResult = 0;
cu_imageArray =0;

m_imageWith = m_imageHeight = 0;
}

OpenGLStatic::~OpenGLStatic()
{
}


BEGIN_MESSAGE_MAP(OpenGLStatic, CStatic)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_PAINT()
END_MESSAGE_MAP()



// OpenGLStatic message handlers



int OpenGLStatic::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CStatic::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
HWND hWnd = GetSafeHwnd();
m_hDC = ::GetDC(hWnd);

if( SetWindowPixelFormat(m_hDC) == FALSE ) return 0;
if( CreateViewGLContext(m_hDC) == FALSE ) return 0;
return 0;
}

void OpenGLStatic::OnDestroy()
{
if(wglGetCurrentContext()!=NULL)
{
wglMakeCurrent(NULL, NULL) ;
}
if (m_hGLContext!=NULL)
{
wglDeleteContext(m_hGLContext);
m_hGLContext = NULL;
}
if(m_pbo)
{
cutilSafeCall(cudaGLUnregisterBufferObject(m_pbo));
glDeleteBuffersARB(1, &m_pbo);
}
if(m_texid)
{
glDeleteTextures(1, &m_texid);
}
if( m_dResult)
{
cutilSafeCall( cudaFree(m_dResult) );
}

CStatic::OnDestroy();
}

void OpenGLStatic::OnSize(UINT nType, int cx, int cy)
{
CStatic::OnSize(nType, cx, cy);

if( cy == 0 )
{
cy =1;
}

m_width = cx;
m_height = cy;

glViewport(0, 0, cx, cy);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// TODO: Add your message handler code here
}

void OpenGLStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CStatic::OnPaint() for painting messages
RenderScence();
}

BOOL OpenGLStatic::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Add your specialized code here and/or call the base class
cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
return CStatic::PreCreateWindow(cs);
}

bool OpenGLStatic::Create(HWND hWnd)
{
m_hDC = ::GetDC(hWnd);
if(SetWindowPixelFormat(m_hDC)==FALSE) return 0;
if (CreateViewGLContext(m_hDC)==FALSE) return 0;

glewInit();
if( !glewIsSupported("GL_VERSION_2_0 GL_ARB_vertex_buffer_object GL_ARB_pixel_buffer_object") )
{
AfxMessageBox(L"required OpenGL extensions missing.");
return 0;
}

glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
return TRUE;
}



void OpenGLStatic::RenderScence()
{
glClear(GL_COLOR_BUFFER_BIT );
glLoadIdentity();


m_dResult = d_reslut;
if(m_pbo && m_texid )
{
//从pbo里面加载texture
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo);
glBindTexture(GL_TEXTURE_2D, m_texid);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_imageWith, m_imageHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);

glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex2f(0, 0);
glTexCoord2d(1, 0); glVertex2f(1, 0);
glTexCoord2d(1, 1); glVertex2f(1, 1);
glTexCoord2d(0, 1); glVertex2f(0, 1);
glEnd();

}

SwapBuffers(m_hDC);
}

bool OpenGLStatic::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |PFD_DRAW_TO_BITMAP
|PFD_DOUBLEBUFFER|PFD_STEREO_DONTCARE//|PFD_SUPPORT_GDI//
|PFD_SUPPORT_OPENGL
|PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc);
if (m_GLPixelIndex==0) // Let's choose a default index.
{
m_GLPixelIndex = 1;
if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof
(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
{
return FALSE;
}
}
if (SetPixelFormat( hDC, m_GLPixelIndex,
&pixelDesc)==FALSE)
{
return FALSE;
}
return TRUE;
}

bool OpenGLStatic::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC);
m_hGLContextShareing = wglCreateContext(hDC);
wglShareLists(m_hGLContextShareing, m_hGLContext);

if (m_hGLContext == NULL)
{
return FALSE;
}
if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)
{
return FALSE;
}
return TRUE;
}

void OpenGLStatic::SetPBOAndTexture(int width, int height)
{
//cudaGLSetGLDevice( cutGetMaxGflopsDeviceId());
m_imageWith = width;
m_imageHeight = height;
int memsize = width*height*sizeof(uchar4);

//生成缓存对象
glGenBuffersARB(1, &m_pbo);
//绑定缓存对象
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo);
//将图像数据拷贝到缓存对象
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, memsize, 0, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
//将缓存对象注册到CUDA
cutilSafeCall(cudaGLRegisterBufferObject(m_pbo));

//生成纹理对象
glGenTextures(1, &m_texid);
glBindTexture(GL_TEXTURE_2D, m_texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_imageWith, m_imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);

}

bool OpenGLStatic::SetGPUImageData(uchar4* inputImageData)
{
if(!inputImageData)
return false;
m_dResult = inputImageData;
return true;
}


然后再主对话框里面开辟一个线程

m_pWinThread = AfxBeginThread( (AFX_THREADPROC)PlayVideo1 , (void*)this);

线程函数里面进行CUDA的运算和opengl的交换
线程函数如下:
UINT PlayVideo( LPVOID pParam )
{

CstaticGLDlg *pWin = ( CstaticGLDlg*)pParam;
wglMakeCurrent(pWin->m_glStatic.m_hDC, pWin->m_glStatic.m_hGLContextShareing );
int nFrame = 0;

unsigned char *d_in = 0;
uchar4* d_result = 0;
uchar4* uchar4_d_in = 0;
cudaArray* cu_imageArray = 0;
for(;;)
{

IplImage* src = cvQueryFrame(pWin->capture);
if(src)
{
nFrame++;
if( nFrame == 1)
{
//初始化GPU数据
cutilSafeCall( cudaMalloc((void**)&d_in,src->width*src->height*3));
cutilSafeCall( cudaMalloc((void**)&d_result, (src->width*src->height*sizeof(uchar4) ) ) );
initTexture(src->width, src->height, d_in, uchar4_d_in, cu_imageArray);

pWin->m_glStatic.SetPBOAndTexture(src->width, src->height);
pWin->m_glStatic.OnSize(0, pWin->m_glStatic.m_width, pWin->m_glStatic.m_height);
}

unsigned int hTimer;
StartTimer(&hTimer);
cutilSafeCall(cudaGLMapBufferObject((void**)&d_result, pWin->m_glStatic.m_pbo));
uchar1_To_uchar4(src, d_in, uchar4_d_in, src->width, src->height);
cylinderProjectionKernel(uchar4_d_in, d_result,cu_imageArray, src->width, src->height, 700);
cutilSafeCall(cudaGLUnmapBufferObject( pWin->m_glStatic.m_pbo));
double gpuTime = StopTimer(hTimer);
TRACE("%f ms\n", gpuTime);
pWin->m_glStatic.RenderScence();

}
else
{
break;
}
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext( pWin->m_glStatic.m_hGLContext);
pWin->m_glStatic.m_hGLContext = NULL;
wglDeleteContext( pWin->m_glStatic.m_hGLContextShareing);
pWin->m_glStatic.m_hGLContextShareing = NULL;
AfxEndThread(0);
return 0;
}

但线程函数运行到AfxEndThread(0);
就出现错误如下:
Unhandled exception at 0x69ba0d49 in RemoteTower.exe: 0xC0000005: Access violation reading location 0x0001de6c.
把语句
pWin->m_glStatic.SetPBOAndTexture(src->width, src->height);
cutilSafeCall(cudaGLMapBufferObject((void**)&d_result, pWin->m_glStatic.m_pbo));
cutilSafeCall(cudaGLUnmapBufferObject( pWin->m_glStatic.m_pbo));
屏蔽掉程序没有问题。
那个大侠能帮我解决下,谢谢。。


...全文
345 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
minwu222 2011-04-02
  • 打赏
  • 举报
回复
问题有了解决方案,不要在工作线程里面共享opengl的DC,工作线程负责处理数据,显示交给显示线程。工作线程用PostMessage发送消息更新就行了。
minwu222 2010-12-16
  • 打赏
  • 举报
回复
这个问题看样子还是难倒了。。。
kirk119 2010-12-15
  • 打赏
  • 举报
回复
持续关注中……

590

社区成员

发帖
与我相关
我的任务
社区描述
CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。
社区管理员
  • CUDA编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧