Опитвам се да напиша OpenCL ядро, което попълва OpenCL изображение със стойности. Въпреки това имах проблеми с това, че на някои тексели не се пише. Изглежда не мога да накарам функцията write_image() да записва в тексели с различни координати x и y.
Създадох програма за намаляване тук. Надяваме се, че това е достатъчно ясно, за да се чете:
#include <iostream>
#include <cassert>
#include <OpenCL/OpenCL.h>
const char* clSource[] = {
"kernel void set(write_only image2d_t image)\n",
"{\n",
" int x = get_global_id(0);\n",
" int y = get_global_id(1);\n",
" float4 result = float4(1.0, 1.0, 1.0, 1.0);\n",
" printf(\"Writing dimensions %d x %d: %d, %d, %d, %d\\n\", x, y,\n",
" (int)result.x*255, (int)result.y*255, (int)result.z*255, (int)result.w*255);\n",
" write_imagef(image, int2(x, y), result);\n",
"}\n",
};
int main(int argc, const char * argv[])
{
const unsigned int WIDTH = 3;
const unsigned int HEIGHT = 3;
cl_int clError;
cl_platform_id platform;
clError = clGetPlatformIDs(1, &platform, nullptr);
assert(clError == CL_SUCCESS);
cl_device_id device;
clError = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
assert(clError == CL_SUCCESS);
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
0
};
cl_context openCLContext = clCreateContext(properties, 1, &device, nullptr, nullptr, &clError);
assert(clError == CL_SUCCESS);
cl_command_queue commandQueue = clCreateCommandQueue(openCLContext, device, 0, &clError);
assert(clError == CL_SUCCESS);
cl_program program = clCreateProgramWithSource(openCLContext, sizeof(clSource) / sizeof(const char*), clSource, nullptr, &clError);
assert(clError == CL_SUCCESS);
clError = clBuildProgram(program, 1, &device, "", nullptr, nullptr);
assert(clError == CL_SUCCESS);
cl_kernel kernel = clCreateKernel(program, "set", &clError);
assert(clError == CL_SUCCESS);
cl_image_format imageFormat;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_RGBA;
cl_image_desc imageDesc;
imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
imageDesc.image_width = WIDTH;
imageDesc.image_height = HEIGHT;
imageDesc.image_depth = 1;
imageDesc.image_array_size = 1;
imageDesc.image_row_pitch = 0;
imageDesc.image_slice_pitch = 0;
imageDesc.num_mip_levels = 0;
imageDesc.num_samples = 0;
imageDesc.buffer = nullptr;
cl_mem clTexture = clCreateImage(openCLContext, CL_MEM_WRITE_ONLY, &imageFormat, &imageDesc, nullptr, &clError);
assert(clError == CL_SUCCESS);
clError = clSetKernelArg(kernel, 0, sizeof(cl_mem), &clTexture);
assert(clError == CL_SUCCESS);
size_t globalWorkOffset[] = {0, 0, 0};
size_t globalWorkSize[] = {WIDTH, HEIGHT, 0};
size_t localWorkSize[] = {1, 1, 0};
cl_event event1;
clError = clEnqueueNDRangeKernel(commandQueue, kernel, 2, globalWorkOffset, globalWorkSize, localWorkSize, 0, nullptr, &event1);
assert(clError == CL_SUCCESS);
unsigned char* bitmap = new unsigned char[WIDTH * HEIGHT * 4];
size_t origin[] = {0, 0, 0};
size_t region[] = {WIDTH, HEIGHT, 1};
cl_event event2;
clError = clEnqueueReadImage(commandQueue, clTexture, CL_TRUE, origin, region, 0, 0, bitmap, 1, &event1, &event2);
std::cout << "============================================" << std::endl;
clError = clWaitForEvents(1, &event2);
assert(clError == CL_SUCCESS);
for (size_t i = 0; i < HEIGHT; ++i) {
for (size_t j = 0; j < WIDTH; ++j) {
std::cout << "Reading dimensions " << j << " x " << i << ": ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+0]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+1]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+2]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+3]) << std::endl;
}
}
delete[] bitmap;
clError = clReleaseEvent(event1);
assert(clError == CL_SUCCESS);
clError = clReleaseEvent(event2);
assert(clError == CL_SUCCESS);
clError = clReleaseMemObject(clTexture);
assert(clError == CL_SUCCESS);
clError = clReleaseKernel(kernel);
assert(clError == CL_SUCCESS);
clError = clReleaseProgram(program);
assert(clError == CL_SUCCESS);
clError = clReleaseCommandQueue(commandQueue);
assert(clError == CL_SUCCESS);
clError = clReleaseDevice(device);
assert(clError == CL_SUCCESS);
clError = clReleaseContext(openCLContext);
assert(clError == CL_SUCCESS);
return 0;
}
След всичко това, ето изхода на OS X (10.9):
Writing dimensions 0 x 0: 255, 255, 255, 255
Writing dimensions 1 x 0: 255, 255, 255, 255
Writing dimensions 2 x 0: 255, 255, 255, 255
Writing dimensions 0 x 1: 255, 255, 255, 255
Writing dimensions 1 x 1: 255, 255, 255, 255
Writing dimensions 2 x 1: 255, 255, 255, 255
Writing dimensions 0 x 2: 255, 255, 255, 255
Writing dimensions 1 x 2: 255, 255, 255, 255
Writing dimensions 2 x 2: 255, 255, 255, 255
============================================
Reading dimensions 0 x 0: 255, 255, 255, 255
Reading dimensions 1 x 0: 0, 0, 0, 0
Reading dimensions 2 x 0: 0, 0, 0, 0
Reading dimensions 0 x 1: 0, 0, 0, 0
Reading dimensions 1 x 1: 255, 255, 255, 255
Reading dimensions 2 x 1: 0, 0, 0, 0
Reading dimensions 0 x 2: 0, 0, 0, 0
Reading dimensions 1 x 2: 0, 0, 0, 0
Reading dimensions 2 x 2: 255, 255, 255, 255
Program ended with exit code: 0
Получавам същия резултат на ATI Radeon HD 5750, както и на NVIDIA GeForce GT 650M.
Проблеми с текстурата на OpenCL към OpenGL и opencl image2d_t не записва обратно стойности изглежда има подобни проблеми, но нито един от тях няма нещо, което да ми помогне.
Правя ли нещо нередно? Или записите на изображения просто не се поддържат от драйверите на Mavericks?