OpenCL - запись данных на устройство
У меня возникают трудности при отправке данных типа CL_HALF_FLOAT на графический процессор AMD HD 7990.
В настоящее время я читаю файл.exr с использованием OpenEXR и сохраняю данные в буфере с именем "пиксели".
// http://www.openexr.com/ReadingAndWritingImageFiles.pdf
Imf::Array2D<Imf::Rgba> pixels; // Input image buffer
try{
std::string fileName = resourcesDirectory + "Input/tunnel/00000.exr"; // Read in test file
std::cout << "Reading " << fileName << std::endl;
Imf::RgbaInputFile file(fileName.c_str()); // Constructor opens the file and reads the files header - dataWindow
Imath::Box2i dataWindow = file.dataWindow(); // File's data window
imageWidth = dataWindow.max.x - dataWindow.min.x + 1; // Width of image
imageHeight = dataWindow.max.y - dataWindow.min.y + 1; // Height of image
pixels.resizeErase(imageHeight, imageWidth); // Performs allocation
// Tell the RgbaInputFile object how to access individual pixels in the buffer
file.setFrameBuffer(&pixels[0][0] - dataWindow.min.x - dataWindow.min.y * imageWidth, 1, imageWidth);
// Copy the pixel data from the file into the buffer
file.readPixels(dataWindow.min.y, dataWindow.max.y);
// How many channels does the image have?
switch (file.channels()){
case Imf::WRITE_RGBA:
numChannels = 4;
break;
case Imf::WRITE_RGB:
numChannels = 3;
break;
default:
throw std::runtime_error("Unable to load EXR files that are not RGBA or RGB");
}
std::cout << "Image has " << numChannels << " channels\n";
}catch (Iex::BaseExc & e){
std::cout << e.what() << std::endl;
}
Я уверен, что изображение корректно читается, потому что, если я использую встроенную функцию OpenEXR для записи файла, используя "пиксели", он производит то же самое выходное изображение.
Создание объекта буфера inputImageBuffer не вызывает ошибок.
// Set Persistent memory only for AMD platform
cl_mem_flags inMemFlags = CL_MEM_READ_ONLY;
if (args->isAmdPlatform()){
inMemFlags |= CL_MEM_USE_PERSISTENT_MEM_AMD; // Faster transfer speed under windows 7
}
cl::Buffer inputImageBuffer;
// Create memory object for input image on the device
inputImageBuffer = cl::Buffer(
context, // Context
inMemFlags, // Flags
imageWidth * imageHeight * numChannels * sizeof(CL_HALF_FLOAT), // Size
NULL, // Host pointer
&status); // Status check
statusCheck(status, "Buffer::Buffer() failed. (inputImageBuffer)");
Однако, когда я пытаюсь отправить данные с помощью функции enqueueWriteBuffer, происходит сбой программы, и полезная отладочная информация не возвращается.
// Copy pixels to inputBufferImage
status = commandQueue.enqueueWriteBuffer(
inputImageBuffer,
CL_TRUE,
0,
imageWidth * imageHeight * numChannels * sizeof(CL_HALF_FLOAT),
&pixels);
statusCheck(status, "Copying failed");
Я думаю, что ошибка может заключаться в том, как я объявляю размер каждого буфера, но я не уверен, и любая помощь будет принята с благодарностью.
Спасибо
2 ответа
Ваша проблема в основном связана с C++ и чрезмерной абстракцией от создателя библиотеки. Array2D не является необработанной плоской памятью, которая потребуется OpenCL enqueueWriteBuffer, и он не обеспечивает какого-либо четкого способа фактического доступа к памяти.
По сути, вы даете ему указатель на экземпляр класса, и он пытается читать с него, а не с _данных, которые на самом деле содержат пиксели. См. http://www.sidefx.com/docs/hdk12.1/_imf_array_8h_source.html о том, как это реализовано.
Вам необходимо получить доступ к фактической памяти, где хранятся пиксели. Вы можете либо поиграть с шаблоном и изменить его, либо вы можете попробовать пиксели [0]. Это может сработать, если реализация будет такой, как на той странице, на которую я ссылаюсь.
Документация OpenExr ужасна в этом отношении, но я уверен, что проблема в том, &pixels
:
status = commandQueue.enqueueWriteBuffer(
inputImageBuffer,
CL_TRUE,
0,
imageWidth * imageHeight * numChannels * sizeof(CL_HALF_FLOAT),
&pixels // <---- error here!
);
Как уже отмечалось, sharpneli, &pixels
это указатель на экземпляр нетривиального класса. Существует очень большая вероятность того, что это не местоположение фактических необработанных данных пикселей. На самом деле я не знаю, где находятся необработанные данные, но каждый пример, который я нашел в документации, использует следующий шаблон:
&pixels[0][0] - dataWindow.min.x - dataWindow.min.y * imageWidth
Так что я думаю, что именно здесь находятся необработанные данные.