Skip to content

What is OWL?

Ingo Wald edited this page Nov 6, 2020 · 2 revisions

OWL is a convenience/productivity-oriented library on top of OptiX 7.x, and aims at making it easier to write OptiX programs by taking some of the more arcane arts (like knowing what a Shader Binding Table is, and how to actually build it), and doing that for the user. For example, assuming the node graph (ie, the programs, geometries, and acceleration structures) have already been built, the shader binding table (SBT) can be built and properly populated by a single call owlBuildSBT(context).

In addition, OWL also allows for somewhat higher-level abstractions than native OptiX+CUDA for operations such as creating device buffers, uploading data, building shader programs and pipelines, building acceleration structures, etc.

Who is OWL designed/intended for?

OWL is particularly targetted at two groups of users: First, those that do want to use GPU Ray Tracing and RTX hardware acceleration, and that are comfortable with typical GPU concepts such as GPU memory vs device memory, ray tracing pipeline, shader programs, and some CUDA programming - but that are not "Ninja" OptiX/Vulkan/DirectX users, and might not be 100% sure about the most nitty-bitty grits of details on SBT data layout and order, or on just how exactly to do the BVH compaction, how exactly to deal with async launches or refitting, etc.

Second, it targets those that do know all these concepts, but would rather spent their time on the actual shader programs and functionality of the program, rather than on doing and all the low-level steps themselves; ie, those that are willing to trade a bit of low-level control (and maybe some tiny amount of performance) for higher developing productivity.

Simple Example

As an example of how easy it is to use OWL to build OptiX data strucutres, the following example code snippet takes a host-based triangle mesh and:

  • uploads the index and vertex buffer to the active GPU(s)
  • creates a triangle mesh geometry with a sample 'color' SBT entry
  • puts this mesh into a triangle bottom-level accel structure (BLAS)
  • builds that acceleration structure, including BVH compaction
  • creates an instance with an instance transform, and finally
  • builds and returns an instance acceleration structure over that.

Note how this little example will do these step: including data upload, set-up of build inputs, BVH construction, BVH compaction, and everything else that's required for this. Though still a relatively benign example, doing the same in low-level CUDA and OptiX code would result in significantly more code that the user would have to write, debug, and maintain.

/* simple sample of setting up a full geometry, BLAS and
   IAS for a simple single-triangle mesh model */
OWLGroup buildBlasAndIas(max3x4f             &instXfm,
                         std::vector<float3> &vtx,
                         std::vector<int3>   &idx,
						 float3               color)
{
   /* upload the buffers */
   OWLBuffer vtxBuffer
      = owlDeviceBufferCreate(ctx,OWL_FLOAT3,
	                          vtx.size(),vtx.data());
   OWLBuffer idxBuffer
      = owlDeviceBufferCreate(ctx,OWL_FLOAT3,
	                          idx.size(),idx.data());
							  
   /* create triangle mesh geometry */
   OWLGeom mesh = owlGeomCreate(ctx,myMeshGT);
   owlTrianglesSetVertices(mesh,vtxBuffer,vtx.size(),
                          /*stride+ofs*/sizeof(vtx[0],0);
   owlTrianglesSetIndices(mesh,vtxBuffer,vtx.size(),
                          /*stride+ofs*/sizeof(idx[0]),0);
						  
   /* create and build triangle BLAS */
   OWLGroup blas = owlTrianglesGroupCreate(ctx,1,&mesh);
   owlGroupBuildAccel(blas);
						  
   /* create and build instance accel struct (IAS) */
   OWLGroup ias = owlInstanceGroupCreate(ctx,1,
       /* instantiated BLASes */&blas,
       /* instance IDs:       */nullptr,
	   /* instance transforms */&instXfm);
   owlGroupBuildAccel(ias);
   return blas; // that's it!
}

Of course, even with OWL there's still much more that needs to be done for a full renderer: For example, in this code we assumed that a context (ctx) and a geometry type for this mesh (myMeshGT) have already been created; the user also still has to set up the programs, create frame buffer and launch data, build the programs (owlBuildPrograms()), the pipline (owlBuildPipeline()), and the SBT (owlBuildSBT(ctx)), etc.

Clone this wiki locally