-
Notifications
You must be signed in to change notification settings - Fork 57
What is OWL?
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.
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.
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.