How to access the data from an output buffer?

Hello,
I am new to optix and would not consider myself to be an expert in c programming nor in programming with cuda.
I am currently working on the tutorials from the optix sdk and would like to process my rendered (ray traced) data in OpenCV.
I have been trying to read the data out of the buffer that is returned by the function “getOutputBuffer()” to do some advanced processing with it, but all I am getting is the reference (adress) to where the buffer data is located.
Can you please tell me how to extract the raw buffer data?

Thanks for your help!

You would need to map the output or input_output buffer for reading, which gives you a host address to the data, read the data, and unmap.
Vice versa for input or input_output buffers: map for write, write, unmap.

Since buffers are the only way to output results in OptiX, that code sequence exists in almost all OptiX examples somewhere.

If you want to start learning OptiX, there is a recent set of “OptiX Introduction” tutorial examples I developed for my GTC 2018 talk. Please find links and more information in this sticky post:
https://devtalk.nvidia.com/default/topic/998546/optix/optix-advanced-samples-on-github/

If you search for “map(” in this file, you will find both read and write buffer mapping cases.
https://github.com/nvpro-samples/optix_advanced_samples/blob/master/src/optixIntroduction/optixIntro_07/src/Application.cpp

If you want to do CUDA-OptiX interop, there are API calls to set and get pointers to buffers explicitly. For more information on that please read the OptiX Programming Guide chapter 9:
http://raytracing-docs.nvidia.com/optix/guide/index.html#cuda#9001
There are multiple topics discussing interop on this forum.

Thank you very much. That helped.

Could you also tell me how to unpack the mapped buffer without using OpenGL?

I would simply like to access the raw data to use it with OpenCV.

Not sure I understand the problem. I have not used OpenCV.

The example code in the provided links contains both paths for OpenGL interop buffers in PBOs (in the “if (m_interop)” blocks) and standard buffers on the host for the output buffers. All other buffers like the LightDefinition, MaterialParameter, attributes, etc. show how to handle user defined structures, for input buffers in these cases, but the same mechanism applies for reading output buffers.

If you map a buffer to a host address, that’s your pointer to the data. Read or write whatever is in that data. You defined the layout.

As far as I can see, the else statement also contains an opengl function to interpret the buffer data:

if (m_interop) 
      {
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_bufferOutput->getGLBOId());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (GLsizei) m_width, (GLsizei) m_height, 0, GL_RGBA, GL_FLOAT, (void*) 0); // RGBA32F from byte offset 0 in the pixel unpack buffer.
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
      }
      else
      {
        const void* data = m_bufferOutput->map(0, RT_BUFFER_MAP_READ);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (GLsizei) m_width, (GLsizei) m_height, 0, GL_RGBA, GL_FLOAT, data); // RGBA32F
        m_bufferOutput->unmap();
      }

I am trying to get the ray traced Image from the data in “optixTutorial3” in Matrix representation.

I am aware of the fact that the data type of the output buffer from the “optixTutorial” is “RT_FORMAT_UNSIGNED_BYTE4”. So I tried to cast a char from the void pointer of the buffer as follows:

void* dat = buf->map(0, RT_BUFFER_MAP_READ);
        char *char_buf = (char*)dat;
        buf->unmap(0);

And tried to print it on the screen with cout. The result were some cryptic signs.
Could you give me a small example of how to access that data so that I can print it out on the screen? Maybe the RGB channels in 8 Bit repesentation or something like that?

The code in the else clause shows how to interpret the data behind the pointer.
Aside from uploading the data to an OpenGL texture, it interprets that user data as RGBA order given as 32-bit floating point components (because the OpenGL’s call argument specifies user data format as GL_RGBA and user type as GL_FLOAT).
Anyway, how you interpret the buffer data is all your responsibility.

If you know that the buffer format is RT_FORMAT_UNSIGNED_BYTE4, then the buffer contents are four unsigned bytes per element.

First, you cast it to signed bytes so your interpretation of the buffer contents is incorrect, unless you just memcpy() it.

Second, if the second code block is all your code, you’re doing it wrong.
The pointer to the mapped buffer is only valid between the map/unmap pair.
You cannot store the pointer to the data and use it outside the map/unmap pair.
That’s why I said: map, read the data, unmap. Every other order is illegal.

Maybe have a look at the optixConsole example which prints an image to the console using characters as greyscales. No OpenGL involved in that. That maps the buffer exactly as you need it.