我正在尝试将 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);
}
它出什么问题了?