我正在尝试使用opencl编写纹理数据,并用opengl显示它。目标是比较具有和不具有互操作性的性能。但现在我无法生成纹理本身。我最初想尝试在没有互操作性的情况下做到这一点:
cl缓冲区初始化和内核创建:
this->imageBuffer = new cl::Image2D(*context, CL_MEM_WRITE_ONLY, cl::ImageFormat(CL_RGBA, CL_FLOAT), this->width, this->height); //this->imageBuffer is a cl::Image*
//create kernel
this->kernel = new cl::Kernel(program, "simple_kernel");
//set kernel arguments
this->kernel->setArg(0, *(this->imageBuffer));
this->kernel->setArg(1, this->offset);
内核执行(发生在循环中(:
cl::size_t<3> origin;
origin[0] = 0; origin[1] = 0; origin[2] = 0;
cl::size_t<3> range;
range[0] = this->width; range[1] = this->height; range[2] = 1;
//Not necessary needed, but shows my point
this->queue->enqueueWriteImage(*(this->imageBuffer), CL_TRUE, origin, range, 0, 0, this->imageOutput);
//enqueue kernel with NDRange
this->queue->enqueueNDRangeKernel(*(this->kernel), cl::NullRange, *(this->global_size), cl::NullRange);
this->queue->enqueueReadImage(*(this->imageBuffer), CL_TRUE, origin, range, 0, 0, this->imageOutput);
this->queue->finish();
std::cout << "fancy output: " << std::endl;;
for(int y = 0; y < this->height; y++) {
for(int x = 0; x < this->width; x++) {
std::cout << this->imageOutput[(y * this->width) + x] << ";";
}
std::cout << std::endl;
}
OpenCL内核:
__kernel void simple_kernel(__global __write_only image2d_t texture, float offset) { //offset is not used for testing
int x = get_global_id(0);
int y = get_global_id(1);
int2 pixelPos = (int2)(x, y);
float4 pixelColor = (float4)(0.5f, 0.0f, 0.0f, 1.0f);
write_imagef(texture, pixelPos, pixelColor);
};
我为类似问题找到的所有解决方案都与glTexImage2D中使用的内部格式和格式有关(在OpenGL渲染部分的开头使用(,所以这里实际上可能是相同的问题,但我没有发现我做错了什么。
预期结果将是一个红色四边形。但它只显示初始化的纹理(在这种情况下是白色的。如果用0.0f初始化,则显示黑色。如果用0.4f初始化,显示灰色(。通过将writeImage也放入队列,我可以缩小内核似乎根本没有改变缓冲区的范围。如果writeImage被注释掉,它将显示一个黑色四边形。因此,读取缓冲区似乎有效,因为在这种情况下,它读取一个空缓冲区(导致黑色四边形(。
花式输出(在内核执行部分的末尾使用(只打印初始化的值(例如1s或0.4s。或者在不使用writeImage时打印0s(
首先,您的"花式输出";部分错误。您的图像具有宽*高*4浮动元素。您将其视为具有width*height元素。
auto pitch = this->width * 4;
std::cout << "fancy output: " << std::endl;
for(int y = 0; y < this->height; y++) {
for(int x = 0; x < this->width; x++) {
auto r = this->imageOutput[(y * pitch) + x * 4 + 0];
auto g = this->imageOutput[(y * pitch) + x * 4 + 1];
auto b = this->imageOutput[(y * pitch) + x * 4 + 2];
auto a = this->imageOutput[(y * pitch) + x * 4 + 3];
std::cout << r << ' ' << g << ' '<< b << ' ' << a << ';';
}
std::cout << 'n';
}
其次,您的内核无法在我的平台上编译,因为您将映像标记为__global
和__write_only image2d_t
。您应该省略__global
。
第三个是您的clEnqueueReadImage
呼叫。当你的行间距应该是width * 4 * sizeof(float)
时,它是0。