2012-12-15 174 views
2

我正在嘗試將OpenCL渲染成OpenGL 256x256紋理。
所有編譯正確的,但只渲染黑屏:OpenGL/OpenCL interop,OpenCL渲染紋理故障

如果關閉紋理,它通常呈現白色矩形。

// Setting up OpenCL 

    const char *source = 
     "__kernel void Main(__write_only image2d_t image)\n" 
     "{\n" 
     " int x = get_global_id(0);\n" 
     " int y = get_global_id(1);\n" 
     " write_imagef(image, (int2)(x, y), (float4)(x/256.0f, y/256.0f, 1.0f, 1.0f));\n" 
     "}\n"; 

    cl_platform_id platform; 
    clGetPlatformIDs(1, &platform, NULL); 

    cl_device_id cdDeviceID; 
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &cdDeviceID, NULL); 

    cl_context_properties props[] = { 
     CL_CONTEXT_PLATFORM, 
     (cl_context_properties)platform, 
     CL_GL_CONTEXT_KHR, 
     (cl_context_properties)wglGetCurrentContext, 
     CL_WGL_HDC_KHR, 
     (cl_context_properties)wglGetCurrentDC, 
    }; 

    *context = clCreateContextFromType(props, CL_DEVICE_TYPE_GPU ,NULL, NULL, NULL); 
    *queue = clCreateCommandQueue(*context, cdDeviceID, 0, NULL); 
    *program = clCreateProgramWithSource(*context, 1, &source, NULL, NULL); 
    clBuildProgram(*program, 1, &cdDeviceID, NULL, NULL, NULL); 
    *kernel = clCreateKernel(*program, "Main", NULL); 
... 
// Setting up texture 

    glEnable(GL_TEXTURE_2D); 

    GLuint texture; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

    cl_mem cl_screen; 
    cl_screen = clCreateFromGLTexture2D(context, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, texture, 0); 
... 
// Rendering 
    clEnqueueAcquireGLObjects(queue, 1, &cl_screen, 0, NULL, NULL); 
    clSetKernelArg(kernel, 0, sizeof(cl_screen), cl_screen); 
    size_t work_size[] = { 256, 256 }; 
    clEnqueueNDRangeKernel(queue, kernel, 2, 0, work_size, 0, 0, NULL, NULL); 
    clEnqueueReleaseGLObjects(queue, 1, &cl_screen, 0, NULL, NULL); 
    clFinish(queue); 

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glBindTexture(GL_TEXTURE_2D, texture); 

    glBegin(GL_QUADS); 
    glTexCoord2i(0, 1); 
    glVertex3f(-1.0f, 1.0f, 0.0f); 
    glTexCoord2i(1, 1); 
    glVertex3f(1.0f, 1.0f, 0.0f); 
    glTexCoord2i(1, 0); 
    glVertex3f(1.0f,-1.0f, 0.0f); 
    glTexCoord2i(0, 0); 
    glVertex3f(-1.0f,-1.0f, 0.0f); 
    glEnd(); 
    glFinish(); 

    SwapBuffers(hDC); 
... 

全碼:

#include <windows.h> 
#include <gl/gl.h> 
#include <CL/cl.h> 
#include <CL/cl_gl.h> 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC); 
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC); 
void EnableOpenCL(cl_kernel * kernel, cl_program * program, cl_context * context, cl_command_queue * queue); 
void DisableOpenCL(cl_kernel * kernel, cl_program * program, cl_context * context, cl_command_queue * queue); 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) 
{ 
    WNDCLASS wc; 
    HWND  hWnd; 
    HDC  hDC; 
    HGLRC hRC; 
    MSG  msg; 
    BOOL  quit = FALSE; 

    wc.style   = CS_OWNDC; 
    wc.lpfnWndProc = WndProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance  = hInstance; 
    wc.hIcon   = LoadIcon(NULL, IDI_APPLICATION); 
    wc.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    wc.lpszMenuName = NULL; 
    wc.lpszClassName = "GLCLInterop"; 

    RegisterClass(&wc); 

    hWnd = CreateWindow("GLCLInterop", "GLCLInterop", WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, hInstance, NULL); 

    cl_kernel  kernel; 
    cl_program  program; 
    cl_context  context; 
    cl_command_queue queue; 

    EnableOpenGL(hWnd, &hDC, &hRC); 
    EnableOpenCL(&kernel, &program, &context, &queue); 

    glEnable(GL_TEXTURE_2D); 

    GLuint texture; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

    cl_mem cl_screen; 
    cl_screen = clCreateFromGLTexture2D(context, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, texture, 0); 

    while (!quit) 
    { 
     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     { 
      if (msg.message == WM_QUIT) 
       quit = TRUE; 
      else 
      { 
       TranslateMessage(&msg); 
       DispatchMessage(&msg); 
      } 
     } 
     else 
     { 
      clEnqueueAcquireGLObjects(queue, 1, &cl_screen, 0, NULL, NULL); 
      clSetKernelArg(kernel, 0, sizeof(cl_screen), cl_screen); 
      size_t work_size[] = { 256, 256 }; 
      clEnqueueNDRangeKernel(queue, kernel, 2, 0, work_size, 0, 0, NULL, NULL); 
      clEnqueueReleaseGLObjects(queue, 1, &cl_screen, 0, NULL, NULL); 
      clFinish(queue); 

      glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
      glClear(GL_COLOR_BUFFER_BIT); 

      glBindTexture(GL_TEXTURE_2D, texture); 

      glBegin(GL_QUADS); 
      glTexCoord2i(0, 1); 
      glVertex3f(-1.0f, 1.0f, 0.0f); 
      glTexCoord2i(1, 1); 
      glVertex3f(1.0f, 1.0f, 0.0f); 
      glTexCoord2i(1, 0); 
      glVertex3f(1.0f,-1.0f, 0.0f); 
      glTexCoord2i(0, 0); 
      glVertex3f(-1.0f,-1.0f, 0.0f); 
      glEnd(); 
      glFinish(); 

      SwapBuffers(hDC); 
     } 
    } 

    DisableOpenGL(hWnd, hDC, hRC); 
    DisableOpenCL(&kernel, &program, &context, &queue); 
    DestroyWindow(hWnd); 

    return msg.wParam; 
} 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 

    switch (message) 
    { 
    case WM_CREATE: 
     return 0; 

    case WM_CLOSE: 
     PostQuitMessage(0); 
     return 0; 

    case WM_DESTROY: 
     return 0; 

    case WM_KEYDOWN: 
     switch (wParam) 
     { 

     case VK_ESCAPE: 
      PostQuitMessage(0); 
      return 0; 

     } 
     return 0; 

    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
} 

void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC) 
{ 
    PIXELFORMATDESCRIPTOR pfd; 
    int format; 

    *hDC = GetDC(hWnd); 

    ZeroMemory(&pfd, sizeof(pfd)); 

    pfd.nSize  = sizeof(pfd); 
    pfd.nVersion = 1; 
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
    pfd.iPixelType = PFD_TYPE_RGBA; 
    pfd.cColorBits = 24; 
    pfd.cDepthBits = 16; 
    pfd.iLayerType = PFD_MAIN_PLANE; 
    format   = ChoosePixelFormat(*hDC, &pfd); 

    SetPixelFormat(*hDC, format, &pfd); 

    *hRC = wglCreateContext(*hDC); 
    wglMakeCurrent(*hDC, *hRC); 
} 

void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC) 
{ 
    wglMakeCurrent(NULL, NULL); 
    wglDeleteContext(hRC); 
    ReleaseDC(hWnd, hDC); 
} 

void EnableOpenCL(cl_kernel * kernel, cl_program * program, cl_context * context, cl_command_queue * queue) 
{ 
    const char *source = 
     "__kernel void Main(__write_only image2d_t image)\n" 
     "{\n" 
     " int x = get_global_id(0);\n" 
     " int y = get_global_id(1);\n" 
     " write_imagef(image, (int2)(x, y), (float4)(x/256.0f, y/256.0f, 1.0f, 1.0f));\n" 
     "}\n"; 

    cl_platform_id platform; 
    clGetPlatformIDs(1, &platform, NULL); 

    cl_device_id cdDeviceID; 
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &cdDeviceID, NULL); 

    cl_context_properties props[] = { 
     CL_CONTEXT_PLATFORM, 
     (cl_context_properties)platform, 
     CL_GL_CONTEXT_KHR, 
     (cl_context_properties)wglGetCurrentContext, 
     CL_WGL_HDC_KHR, 
     (cl_context_properties)wglGetCurrentDC, 
    }; 

    *context = clCreateContextFromType(props, CL_DEVICE_TYPE_GPU ,NULL, NULL, NULL); 

    *queue = clCreateCommandQueue(*context, cdDeviceID, 0, NULL); 

    *program = clCreateProgramWithSource(*context, 1, &source, NULL, NULL); 
    clBuildProgram(*program, 1, &cdDeviceID, NULL, NULL, NULL); 

    *kernel = clCreateKernel(*program, "Main", NULL); 
} 

void DisableOpenCL(cl_kernel * kernel, cl_program * program, cl_context * context, cl_command_queue * queue) 
{ 
    clReleaseKernel(*kernel); 
    clReleaseProgram(*program); 
    clReleaseContext(*context); 
    clReleaseCommandQueue(*queue); 
} 

這有什麼錯呢?

+2

這個網站是不適合審覈200多行代碼。請1)將代碼縮短爲最小數量2)清楚地解釋出現了什麼問題 – Pubby

+1

我必須支持這個問題,因爲很少見的代碼格式正確。製作SSCCE並將其發佈到此處,我們會盡力提供幫助。 –

+1

嘗試在glBegin(GL_QUADS)之前插入glColor4ub(255,255,255,255),然後檢查CL調用返回的狀態。 –

回答

2

您的圖片是GL_UNSIGNED_BYTE,但您使用的是write_imagef。切換到GL_FLOAT或write_imageui。

+0

這不可能是正確答案,即使這解決了您的問題。如果使用RGBA8和無符號字節創建GL紋理,則可以使用read_imagef和write_imagef很好地訪問它!看看OpenCL規範,詳細討論它。 – St0fF