OpenCL - запись данных на устройство

77
7

Мне трудно отправлять данные типа 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 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");

Я думаю, что ошибка может заключаться в том, как я объявляю размер каждого буфера, но я не уверен, и любая помощь будет высоко оценена.

спасибо

спросил(а) 2021-01-25T22:35:17+03:00 4 месяца, 2 недели назад
1
Решение
108

Документация 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

Поэтому я предполагаю, что это исходные данные.

ответил(а) 2021-01-25T22:35:17+03:00 4 месяца, 2 недели назад
46

Ваша проблема связана в основном с C++ и чрезмерной абстракцией от создателя библиотеки. Array2D не является сырой плоской памятью, которая понадобится OpenCL enqueueWriteBuffer, и она не обеспечивает четкого способа фактического доступа к памяти.

Вы в основном даете ему указатель на экземпляр класса, и он пытается прочитать это, а не из _data, который фактически содержит пиксели. См. Http://www.sidefx.com/docs/hdk12.1/_imf_array_8h_source.html о том, как это реализовано.

Вам нужно получить доступ к фактической памяти, где хранятся пиксели. Вы можете либо играть с шаблоном, либо изменить его, либо попробовать пиксели [0]. Он может работать, если реализация выполняется на той странице, с которой я связан.

ответил(а) 2021-01-25T22:35:17+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема