【发布时间】:2015-06-02 12:48:30
【问题描述】:
我正在使用 openCL 实现光线追踪器。我已经安装了 NVidia 的 CUDA sdk,一切似乎都设置得很好,我的两个平台都被检测到(英特尔和英伟达),并且每个平台都能看到它的设备(英特尔有 HD Graphics 4000,英伟达有我的 GPU:GeForce GT 630M)。
我的问题是我可以使用 Intel 平台运行我的应用程序,但不能使用 Nvidia 的平台。我不认为问题出在我的代码中,但这是我的设备代码:
#include "constants.h" //only a couple of #define
typedef struct Sphere {
float x, y, z;
float radius;
float r, g, b;
}Sphere;
float hit(Sphere s, float ox, float oy, float *n) {
float radius = s.radius;
float dx = ox - s.x;
float dy = oy - s.y;
if (dx*dx + dy*dy < radius*radius) {
float dz = sqrt(radius*radius - dx*dx - dy*dy);
*n = dz / sqrt(radius * radius);
return dz + s.z;
}
return -INF;
}
__kernel void rayTracer(__global Sphere* spheres, write_only image2d_t res) {
// Get the index of the current element to be processed
int x = get_global_id(0);
int y = get_global_id(1);
int ox = x - WIDTH / 2;
int oy = y - HEIGHT / 2;
float r = 0, g = 0, b = 0;
float maxz = (float) -INF;
for (int i = 0; i<NUM_SPHERES; i++)
{
float n;
float t = hit(spheres[i], ox, oy, &n);
if (t > maxz)
{
float fscale = 1;
r = spheres[i].r * fscale;
g = spheres[i].g * fscale;
b = spheres[i].b * fscale;
}
}
write_imagei(res, (int2)(x, y), (int4)(r, g, b, 0));
}
我的主机应用程序也很简单。我只是初始化 openCL 结构,设置数据,然后将其读回。
同样,当使用英特尔平台时,我的应用程序运行良好,我可以看到光线追踪图像。在使用英伟达的时候,虽然API错误码总是0,但是没有结果。
有没有人有任何想法可能是什么问题?
提前致谢
---编辑---
这是一些主机代码
设置 OpenCL 结构:
//Setup OpenCL
cl_platform_id platform = getPlatforms();
cl_device_id device = getDevices(platform, CL_DEVICE_TYPE_GPU);
cl_context_properties ctxProps[] =
{
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
0, 0
};
cl_context ctx = clCreateContext(ctxProps, 1, &device, NULL, NULL, &err);
cl_command_queue queue1 = clCreateCommandQueue(ctx, device, NULL, &err);
GetPlatforms 和 GetDevices 是要求用户选择平台和设备的函数
创建程序并构建它:
cl_program prog = clCreateProgramWithSource(ctx, 1, srcs, &srcSize, &err);
err = clBuildProgram(prog, 1, &device, NULL, NULL, NULL);
if (err < 0)
{
//PRINT BUILD ERROR
size_t log_size;
clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
char* log = (char*)calloc(log_size + 1, sizeof(char));
clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, log_size + 1, log, NULL);
printf("%s/n", log);
free(log);
std::cin >> err;
return 1;
}
cl_kernel krn = clCreateKernel(prog, "rayTracer", &err);
//....CREATE SOME SPHERES...
//Setup device data
cl_image_format fmt;
fmt.image_channel_order = CL_RGBA;
fmt.image_channel_data_type = CL_UNSIGNED_INT8;
cl_mem spheresBuff = clCreateBuffer(ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, spheres.size() * sizeof(Sphere), spheres.data(), &err);
cl_mem resBuff = clCreateImage2D(ctx, CL_MEM_WRITE_ONLY, &fmt, WIDTH, HEIGHT, 0, NULL, &err);
//Setup kernel arguments
err = clSetKernelArg(krn, 0, sizeof(cl_mem), (void*)&spheresBuff);
err = clSetKernelArg(krn, 1, sizeof(cl_mem), (void*)&resBuff);
//Run kernel
size_t gSize[] = { WIDTH, HEIGHT };
err = clEnqueueNDRangeKernel(queue1, krn, 2, NULL, gSize, NULL, 0, NULL, NULL);
//Read result
Image img = createRGBAImage(WIDTH, HEIGHT);
size_t origin[] = { 0, 0, 0 };
size_t region[] = { WIDTH , HEIGHT , 1 };
err = clEnqueueReadImage(queue1, resBuff, CL_TRUE, origin, region, 0, 0, img.pixel.data(), 0, NULL, NULL);
【问题讨论】:
-
当你说'不显示结果'时,你的意思是结果图像是空白的吗?您能否向我们展示一些相关的主机代码(OpenCL 缓冲区/图像的创建、内核排队、主机设备传输)?
-
呼应@jprice 在别处所说的:您是否在每个 API 调用中检查状态错误返回值?
-
我已经放了一些主机代码。虽然其中没有错误检查代码,但我已经调试了应用程序并且错误变量始终为 0
-
是的,我的意思是生成的图像是空白的
-
alpha值不应该是1,而不是0吗?此外,您应该使用
write_imageui而不是write_imagei,因为您的图像是CL_UNSIGNED_INT8,尽管我不确定这在实践中会有多大影响。