OpenGL/OpenCL 互操作、OpenCL 渲染到纹理的麻烦

2024-01-21

我正在尝试将 OpenCL 渲染为 OpenGL 256x256 纹理。
全部编译正确,但仅呈现黑屏:

如果关闭纹理,它通常会渲染白色矩形。

// 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);
}

它出什么问题了?


您的图像是 GL_UNSIGNED_BYTE,但您正在使用 write_imagef。切换到 GL_FLOAT 或 write_imageui。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL/OpenCL 互操作、OpenCL 渲染到纹理的麻烦 的相关文章

随机推荐