Nitrous is designed to run in a separate nitrous rendering thread. For thread-safety, plug-ins must use SmartHandle
to access the pointers of Nitrous resources including buffers, textures, render items, materials, and others in main thread or nitrous rendering thread.
SmartHandle
can be considered as smart pointers. Each SmartHandle
holds a reference to a resource. More than one SmartHandle
can refer to the same resource. In this case, the resource is not freed until the last SmartHandle
releases its reference.
The Nitrous SDK provides a list of strong typed handles. These handles are derived from SmartHandle
and they have no data members, but several methods for plug-ins to manipulate the underlying resources.
The following figure shows the smarthandle
types in the Nitrous SDK:
SmartHandle
By default, a SmartHandle
references a null object and is invalid. To make the SmartHandle
valid, the plug-ins must initialize the SmartHandle
or assign another valid SmartHandle
to the SmartHandle
.
The following example illustrates how to create a valid GeometryRenderItemHandle
and how to use it:
GeometryRenderItemHandle hRenderItem;
assert(!hRenderItem.IsValid()); // Is invalid at this time
hRenderItem.Initialize();
assert(hRenderItem.IsValid()); // Is valid now
GeometryRenderItemHandle hRenderItem2;
// Both hRenderItem and hRenderItem2 reference to the same
// underlying geometry resource
hRenderItem2 = hRenderItem;
// Two render items are equal to each other now
assert(hRenderItem == hRenderItem2);
hRenderItem.SetMaterialID(31583); // Set a random material ID
assert(hRenderItem2.GetMaterialID() == 31583); // Should be the same
The SmartHandle
methods can be categorized into two groups: write type and read type.
Any function call that does not send data from the underlying resource to the calling thread is considered a write type function. All calls to these functions are pushed to a thread-safe command queue. Nitrous chooses a proper time to flush all commands in the command queue to synchronize the underlying resource.
The SmartHandle
caches the data members that cannot be changed by the rendering thread. If the plug-in needs the member data of the underlying resource, the SmartHandle
returns the cached data when applicable. However, in certain cases, if the plug-in wants to retrieve a member data that requires computation in the rendering thread, Nitrous flushes all commands in the command queue, sends a data retrieving command, and waits for the rendering thread to return the result. During this process, the calling thread is blocked and the command queue is locked for exclusive use by the SmartHandle
.
Plug-ins must avoid using the read functions of SmartHandle
whenever possible because SmartHandle
is write friendly but not read friendly.