Minimize what needs to be done per-event by placing everything possible into once only initialization.
Clearly split:
Do multi-event propagations to test the split.
Application Specific Information:
terminating with uncaught exception of type optix::Exception: Invalid value (Details: Function "RTresult _rtContextValidate(RTcontext)" caught exception: Non-initialized variable record_buffer: Buffer(1d, 8 byte element), file:/Users/umber/workspace/rel4.0-mac64-build-Release/sw/wsapps/raytracing/rtsdk/rel4.0/src/Context/ValidationManager.cpp, line: 118)
abort() called
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
8 libOptiXRap.dylib 0x000000010afa8eb9 optix::ContextObj::checkError(RTresult) const + 121 (optixpp_namespace.h:1832)
9 libOptiXRap.dylib 0x000000010afa8f17 optix::ContextObj::validate() + 55 (optixpp_namespace.h:1877)
10 libOptiXRap.dylib 0x000000010afbae9e OContext::launch(unsigned int, unsigned int, unsigned int, unsigned int, OTimes*) + 542 (OContext.cc:237)
11 libOptiXRap.dylib 0x000000010afce036 OPropagator::prelaunch() + 390 (OPropagator.cc:328)
12 libOptiXRap.dylib 0x000000010afcae69 OEngineImp::preparePropagator() + 1081 (OEngineImp.cc:188)
13 libOptiXRap.dylib 0x000000010afc8f42 OEngineImp::init() + 66 (OEngineImp.cc:82)
14 libOptiXRap.dylib 0x000000010afc8ed4 OEngineImp::OEngineImp(OpticksHub*) + 228 (OEngineImp.cc:73)
15 libOptiXRap.dylib 0x000000010afc8f6d OEngineImp::OEngineImp(OpticksHub*) + 29 (OEngineImp.cc:73)
16 libOpticksOp.dylib 0x000000010b4b52df OpEngine::OpEngine(OpticksHub*) + 95 (OpEngine.cc:23)
17 libOpticksOp.dylib 0x000000010b4b534d OpEngine::OpEngine(OpticksHub*) + 29 (OpEngine.cc:27)
18 libGGeoView.dylib 0x000000010b5aac9f OKPropagator::OKPropagator(OpticksHub*, OpticksIdx*, OpticksViz*) + 143 (OKPropagator.cc:38)
19 libGGeoView.dylib 0x000000010b5aaefd OKPropagator::OKPropagator(OpticksHub*, OpticksIdx*, OpticksViz*) + 45 (OKPropagator.cc:46)
20 libGGeoView.dylib 0x000000010b5aa12f OKMgr::OKMgr(int, char**) + 575 (OKMgr.cc:37)
21 libGGeoView.dylib 0x000000010b5aa453 OKMgr::OKMgr(int, char**) + 35 (OKMgr.cc:45)
22 OKTest 0x00000001073fba38 main + 1368 (OKTest.cc:60)
23 libdyld.dylib 0x00007fff8a86f5fd start + 1
Host access to the data stored within a buffer is performed with the rtBufferMap function. This function returns a pointer to a one dimensional array representation of the buffer data. All buffers must be unmapped via rtBufferUnmap before context validation will succeed.
OpenGL buffer objects like PBOs and VBOs can be encapsulated for use in OptiX with rtBufferCreateFromGLBO.
You can take a look at most of the resize function for the windowing in the Optix SDK:
_context["eyeHitBuffer"]->getBuffer()->setSize(NEW_WIDTH, NEW_HEIGHT);
If the contents of your VBO will be dynamic, should you call glBufferData or glBufferSubData (or glMapBuffer)? If you will be updating a small section, use glBufferSubData. If you will update the entire VBO, use glBufferData (this information reportedly comes from a nVidia document). However, another approach reputed to work well when updating an entire buffer is to call glBufferData with a NULL pointer, and then glBufferSubData with the new contents. The NULL pointer to glBufferData lets the driver know you don’t care about the previous contents so it’s free to substitute a totally different buffer, and that helps the driver pipeline uploads more efficiently.
Another thing you can do is double buffered VBO. This means you make 2 VBOs. On frame N, you update VBO 2 and you render with VBO 1. On frame N+1, you update VBO 1 and you render from VBO 2. This also gives a nice boost in performance for nVidia and ATI/AMD.
To resize, needs to call glBufferData again,
718 void Scene::uploadEvent(OpticksEvent* evt)
719 {
720 if(!evt)
721 {
722 LOG(fatal) << "Scene::uploadEvt no evt " ;
723 assert(evt);
724 }
725
726 // The Rdr call glBufferData using bytes and size from the associated NPY
727 // the bytes used is NULL when npy->hasData() == false
728 // corresponding to device side only OpenGL allocation
729
730 if(m_genstep_renderer)
731 m_genstep_renderer->upload(evt->getGenstepAttr());
732
733 if(m_nopstep_renderer)
734 m_nopstep_renderer->upload(evt->getNopstepAttr(), false);
735
736 if(m_photon_renderer)
737 m_photon_renderer->upload(evt->getPhotonAttr());
738
739
740 uploadRecordAttr(evt->getRecordAttr());
The upload creates new OpenGL buffer object and copies to it:
272 void Rdr::upload(NPYBase* npy, ViewNPY* vnpy)
273 {
274 // handles case of multiple mvn referring to the same buffer without data duplication,
275 // by maintaining a list of NPYBase which have been uploaded to the Device
276
277 prepare_vao();
278
279 MultiViewNPY* parent = vnpy->getParent();
280 assert(parent);
281
282 bool dynamic = npy->isDynamic();
283
///
/// hmm notion of buffer identity used to see if
// uploaded already is coming from the host npy
/// not from the buffer_id
///
284 if(m_device->isUploaded(npy))
285 {
286 GLuint buffer_id = npy->getBufferId();
287 log("Rdr::upload BindBuffer to preexisting buffer_id:",buffer_id) ;
288 assert(buffer_id > 0);
289 glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
290 }
291 else
292 {
293 void* data = npy->getBytes();
294 unsigned int nbytes = npy->getNumBytes(0) ;
295
296 char repdata[16] ;
297 snprintf( repdata, 16, "%p", data );
298
299 GLuint buffer_id ;
300 glGenBuffers(1, &buffer_id);
301 glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
302
303 LOG(info) << " up "
304 << std::setw(15) << parent->getName()
305 << std::setw(5) << vnpy->getName()
306 << " count " << std::setw(8) << vnpy->getCount()
307 << " shape " << std::setw(20) << vnpy->getShapeString()
308 << " buffer_id " << std::setw(5) << buffer_id
309 << " data " << std::setw(16) << repdata
310 << " hasData " << std::setw(5) << ( npy->hasData() ? "Y" : "N" )
311 << " nbytes " << std::setw(10) << nbytes
312 << " " << (dynamic ? "GL_DYNAMIC_DRAW" : "GL_STATIC_DRAW" )
313 ;
314
315 glBufferData(GL_ARRAY_BUFFER, nbytes, data, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW );
316
317 npy->setBufferId(buffer_id);
318 m_device->add(npy);
319 }
320 }