write_imagef 似乎没有改变任何值

write_imagef seems to not change any values

我正在尝试使用 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 时打印 0)这一事实得到了加强

首先,您的“花式输出”部分是错误的。 您的图片有 width * height * 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