Je fais mes premiers pas bancaux avec OpenCL (l'API C++) et j'ai rencontré un problème où je suis à bout de nerfs et je n'ai aucune idée de quoi peut-être tort. Lors de la définition de l'argument du noyau image2d_t (voir le code distillé ci-dessous), l'appel se déclenche et renvoie le code d'erreur -50 (= CL_INVALID_ARG_VALUE) et je n'ai aucune idée de la raison. J'utilise la plateforme Intel OpenCL et mon CPU (OpenCL 2.0) et j'ai pu compiler et exécuter d'autres exemples de code sans aucun problème.C++ OpenCL kernel retourne CL_INVALID_ARG_VALUE pour __read_only image2d_t
#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <CL/cl2.hpp>
std::string my_kernel = R"(
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE;
__kernel void simple_copy( __read_only image2d_t input_image
, __write_only image2d_t output_image
)
{
int2 coords;
coords.x = get_global_id(0);
coords.y = get_global_id(1);
float4 value = read_imagef(input_image, sampler, coords);
write_imagef(output_image, coords, value);
})";
int main()
{
try
{
//define source and destination image data
constexpr unsigned channels = 4, width = 2, height = 2;
std::array<std::uint8_t, channels*width*height> source = { 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255 };
std::array<std::uint8_t, channels*width*height> destination{}; //value initialization
//initialize OpenCL
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
auto platform = platforms.front();
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
auto device = devices.front();
auto context = cl::Context(device);
auto queue = cl::CommandQueue(context, device);
//create OpenCL image buffers
auto image_format = cl::ImageFormat(CL_RGBA, CL_UNSIGNED_INT8);
auto input_image = cl::Image2D(context, CL_MEM_READ_ONLY, image_format, width, height);
auto output_image = cl::Image2D(context, CL_MEM_WRITE_ONLY, image_format, width, height);
//transfer source image data to device
auto origin = cl::array<cl::size_type, 3U>{0, 0, 0};
auto region = cl::array<cl::size_type, 3U>{width, height, 1};
queue.enqueueWriteImage(input_image, CL_TRUE, origin, region, 0, 0, &source[0]);
//compile device code, retrieve kernel, set kernel arguments
auto program = cl::Program(my_kernel, CL_TRUE);
auto kernel = cl::Kernel(program, "simple_copy");
kernel.setArg(0, input_image); //ERROR: throws -50 (= CL_INVALID_ARG_VALUE) ... why?!
kernel.setArg(1, output_image);
//enqueue copy kernel
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(width, height), cl::NullRange);
//read result back to host
queue.enqueueReadImage(output_image, CL_TRUE, origin, region, 0, 0, &destination[0]);
//output result
for (auto const & val : destination)
{
std::cout << val << " ";
}
std::cout << std::endl;
}
catch (cl::Error & e)
{
std::cout << "caught OpenCL exception - what: " << e.what() << " err: " << e.err() << std::endl;
}
std::string str;
std::getline(std::cin, str);
return 0;
}
merci, ce fut en effet la source de problème! Savez-vous par hasard pourquoi l'appel sans contexte ou périphérique est même autorisé? (Je suppose qu'il est supposé utiliser le contexte/périphérique par défaut si j'en avais défini un? Cependant, je ne vois pas pourquoi il ne lance pas s'il n'y a pas de défaut ...?) –
Il utilisera le contexte par défaut et créera un si l'un n'existe pas. Je suis d'accord que c'est un peu déroutant quand faire ce que je veux dire ne fait pas ce que vous pensiez. –