2014-01-03 2 views
0

У меня возникли трудности с отправкой данных типа CL_HALF_FLOAT на графический процессор AMD HD 7990.OpenCL - Запись данных на устройство

В настоящее время я читаю .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"); 

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

Спасибо

ответ

0

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

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

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

+0

Благодарим вас за ответ. Проведя еще несколько исследований за последний час, я начал смотреть на то, как доступ к «пиксельным» данным был открыт в OpenCL enqueueWriteBuffer. Хотя я не знал точно, что случилось, у меня возникло ощущение, что это может быть проблемой, и ваш ответ имеет смысл. Я решил использовать OpenCV вместо OpenEXR, и теперь он работает нормально. Хотя я могу вернуться позже и изменить шаблон, который вы связали, спасибо еще раз. – user12967

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 

Так что я думаю, что это где исходные данные.

+0

Я тестировал шаблон, который вы нашли, но, к сожалению, программа вылетает, думаю, я буду придерживаться OpenCV. Спасибо за ваш ответ. – user12967

Смежные вопросы