0

我很难将 CL_HALF_FLOAT 类型的数据发送到 AMD HD 7990 GPU。

目前我正在使用 OpenEXR 读取 .exr 文件并将数据存储在名为“像素”的缓冲区中。

// 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");

我认为错误可能在于我如何声明每个缓冲区的大小,但我不确定,任何帮助将不胜感激。

谢谢

4

2 回答 2

0

您的问题主要源于 C++ 和库制造商的过度抽象。Array2D 不是 OpenCL enqueueWriteBuffer 需要的原始平面内存,并且它没有提供任何明确的方式来实际访问内存。

您基本上是给它一个指向类实例的指针,它会尝试从中读取,而不是从实际包含像素的 _data 中读取。请参阅http://www.sidefx.com/docs/hdk12.1/_imf_array_8h_source.html了解它的实施方式。

您需要访问保存像素的实际内存。您可以摆弄模板并更改它,或者您可以尝试像素 [0]。如果实现与我链接的那个页面上的一样,它可能会起作用。

于 2014-01-03T22:09:21.983 回答
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

所以我想这就是原始数据所在的地方。

于 2014-01-03T22:16:54.013 回答