Pipeline Data

From K-3D

Jump to: navigation, search

Overview

As data moves through the Visualization Pipeline, it is critical for performance and memory usage that we minimize deep-copying of data - a mesh might pass through tens-to-hundreds of modifiers before it is rendered, making it impractical for each modifier to naively deep-copy its inputs. In-general, each modifier should only deep-copy the arrays that it modifies, allowing the remaining arrays to be shallow-copied to its output. The K-3D Geometric Primitive data structures provide good granularity for this behavior, but a data structure is still needed to effectively manage the storage for objects that move through the pipeline.

API

k3d::pipeline_data acts as a type of shared smart pointer that provides API specific to pipeline data operations. It is used in all of the mesh and related data structures to store data that should be shallow-copied by-default as it moves through the pipeline:

class mesh
{
  ...
  pipeline_data<points_t> points;
  pipeline_data<selection_t> point_selection;
  std::vector<pipeline_data<primitive> > primitives;
  ...
};
  • Internally, k3d::pipeline_data uses boost::shared_ptr for storage, so assignment of k3d::pipeline_data automatically creates shallow copies:
MeshA.points = MeshB.points; // MeshA now contains a shared copy of MeshB's points.
Output = Input; // Output now contains shared copies of Input's arrays / primitives.
  • The k3d::pipeline_data API provides typical const T* operator->() const and const T& operator*() const methods that allow input data to be accessed read-only. Thus code of the form:
if(!Input.points)
  return;
const k3d::mesh::points_t& input_points = *Input.points;

Output.points->resize(100);

Note from the example that it is still always necessary to avoid dereferencing NULL objects!

  • The k3d::pipeline_data interface provides several overloaded T& create() methods that allow developers to create an object and assign it to a local variable in one-step, for immediate use. This makes it possible to replace code of the form
boost::shared_ptr<k3d::mesh::points_t> points(new k3d::mesh::points_t());
...
Mesh.points = points;

with

k3d::mesh::points_t& points = Output.points.create();
...
  • Several of the k3d::pipeline_data T& create() overloads accept a pointer to the object to be held, allowing developers to pass arguments to the new objects' constructors - particularly useful when the final size of array is known in advance:
k3d::mesh::points_t& points = Output.points.create(new k3d::mesh::points_t(point_count));
k3d::mesh::selection_t& point_selection = Output.point_selection.create(new k3d::mesh::selection_t(point_count, 0));
  • The k3d::pipeline_data API provides the T& writable() method that provides read-write access to output data. The writable() method ensures that shared input data is never overwritten. Typical usage is as follows:
if(!Output.points)
  return;

k3d::mesh::points_t& points = Output.points.writable();

Note that writable() is a type of dereferencing, so it is still necessary to test for NULL pointers before using it!

See Also

Personal tools