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

Так что я думаю, что именно здесь находятся необработанные данные.

Другие вопросы по тегам