Host access to Buffer

OptiX manual provides an example of host access to buffer

unsigned int width, height;
rtBufferGetSize2D( buffer, &width, &height );
void* data;
rtBufferMap( buffer, &data );
rgb* rgb_data = (rgb*)data;
for( unsigned int i = 0; i < width*height; ++I ) {
rgb_data[i].r = rgb_data[i].g = rgb_data[i].b =0.0f;
}
rtBufferUnmap( buffer );

But I found in this way, there is always an error :
Invalid value (Details: Function “RTresult _rtContextCompile(RTcontext)” caught exception: Initalization of non-primitive type buffer: Buffer object, [1769653])

unsigned int width, height;
<b><u>Variable buffer_a = context["buffer_a"];</u></b>
rtBufferGetSize2D( buffer, &width, &height );
void* data;
rtBufferMap( buffer, &data );
<u><b>buffer_a->set(buffer);</b></u>
rgb* rgb_data = (rgb*)data;
for( unsigned int i = 0; i < width*height; ++I ) {
rgb_data[i].r = rgb_data[i].g = rgb_data[i].b =0.0f;
}
rtBufferUnmap( buffer );

So I attach this Buffer with an OptiX Variable “buffer_a” and no more such error again. I wonder why I never succeed without doing this. Did I miss something in the manual?

My recollection is that the c++ API overload for Context::operator will check if the buffer has been created, and if not, will create it, so you can go ahead and use it without first creating it yourself. However, the C API requires that you manually create and init your buffer before using it. This may explain the error you’re seeing. Are you calling

rtSetBufferFormat(buffer, ...)

or

rtBufferSetElementSize(buffer, ...); rtBufferSetSize{1|2|3}D(buffer, ...)

before using it?

Yes, anthony. I specified buffer’s size, format, dimentionality etc before using it. Here is another try with C++ API, and comes the same error :

Details: Function “RTresult _rtContextCompile(RTcontext)” caught exception: Initalization of non-primitive type random_buffer: Buffer object

Buffer random_buffer = context->createBuffer( RT_BUFFER_INPUT, 
                       RT_FORMAT_FLOAT, width, height );

void* data = random_buffer->map();
float* hostData = (float*)data;

<b>...Calculation of hostData...</b>

random_buffer->unmap();

OS : Debian GNU/Linux 7.4 (wheezy)
CUDA : 5.5.22
OptiX : 3.5.1

Any ideas?

Since the exception stems from “rtContextCompile” I guess you try to access the buffer in a OptiX program without having attached it to the context.

How does your OptiX program look like?

what do you mean by attaching buffer to the context? I declared the buffer at the top of cuda file and use it in ray generation program :

rtBuffer<float, 2> random_buffer;
rtDeclareVariable(uint2, launch_index, rtLaunchIndex, );

RT_PROGRAM void ray_gen()
{
  float3 ray_origin = make_float3(random_buffer[launch_index],
  random_buffer[launch_index],random_buffer[launch_index]);

  ...

}

You try to use the buffer in the cuda-file using the name “random_buffer”.
But you do not tell the OptiX context what buffer corresponds to this name.

This is the reason for the exception.

On the host side, you must tell the OptiX context which buffer is “connected” to the name “random_buffer” which is then accessed on the device side. You can do this using the C or the C++ API.

So this is the very first question I asked at beginning : I wonder why the buffer never works without attaching it to an OptiX Variable. Because in the manual when it introduces host access to buffer, it doesn’t mention that it’s necessary to combine the buffer with a context.

Here is the code example for host-side from manual :

RTcontext context = ...;
RTbuffer buffer;
typedef struct { float r; float g; float b; } rgb;
rtBufferCreate( context, RT_BUFFER_INPUT_OUTPUT,
&buffer );
rtBufferSetFormat( RT_FORMAT_USER );
rtBufferSetElementSize( sizeof(rgb) );
rtBufferSetSize2D( buffer, 512, 512 );

// Using the buffer created above
unsigned int width, height;
rtBufferGetSize2D( buffer, &width, &height );
void* data;
rtBufferMap( buffer, &data );
rgb* rgb_data = (rgb*)data;
for( unsigned int i = 0; i < width*height; ++I ) {
rgb_data[i].r = rgb_data[i].g = rgb_data[i].b =0.0f;
}
rtBufferUnmap( buffer );

Within OptiX program

rtBuffer<rgb, 2> buffer;
...
uint2 index = ...;
float r = buffer[index].r;

You may find nowhere above it combines buffer with context, isn’t it weird?

So I had to double check the manual to see if you’re right, and you are. The Programming Guide in the buffer chapter doesn’t explicitly say the buffer needs to be set with a name. Like m_sch said, this is something you need to do (and it looks like you’ve figured that out). Something like:

rtContextDeclareVariable( *context, "buffer", &buffer );

I would recommend using the SDK for code examples and not the programming guide. The guide more-or-less supplies snippets of incomplete code.

Exactly!
Actually I work with the SDK and just curious about why such non-introduced declaration should be used. I thought I missed something important in the manual.
Thanks a lot for your advice, over0219.