Commit 4aad3c6a authored by Will Schroeder's avatar Will Schroeder

Added vtkSMPTools integration to thread algorithm

Each of the three passes of the algorithm has been integrated
into the vtkSMPTools. This enables TBB and X-Kaapi support (as
well as well as sequential and simple vtkMultiThreader
capabilities). Note that there is no distinction between a serial
and parallel version of FlyingEdges (i.e., separate implementations).
parent 17dd6c5c
......@@ -23,6 +23,7 @@
#include "vtkPolyData.h"
#include "vtkFloatArray.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkSMPTools.h"
#include <math.h>
......@@ -91,6 +92,7 @@ public:
int Axis2;
// Output data. Threads write to partitioned memory.
T *Scalars;
T *NewScalars;
vtkIdType *NewLines;
float *NewPoints;
......@@ -216,8 +218,8 @@ EdgeCases[16][5] = {
// Instantiate and initialize key data members. Mostly we build some
// acceleration structures from the case table.
template <class T> vtkFlyingEdges2DAlgorithm<T>::
vtkFlyingEdges2DAlgorithm():XCases(NULL),EdgeMetaData(NULL),NewScalars(NULL),
NewLines(NULL),NewPoints(NULL)
vtkFlyingEdges2DAlgorithm():XCases(NULL),EdgeMetaData(NULL),Scalars(NULL),
NewScalars(NULL),NewLines(NULL),NewPoints(NULL)
{
int j, eCase, numLines;
const unsigned char *edgeCase;
......@@ -576,6 +578,54 @@ unsigned long vtkFlyingEdges2D::GetMTime()
return ( mTime2 > mTime ? mTime2 : mTime );
}
//----------------------------------------------------------------------------
// Build threading integration with the SMPTools
template <class T>
class vtkFlyingEdgesPass1
{
public:
vtkFlyingEdges2DAlgorithm<T> *Algo;
double Value;
void operator()(vtkIdType row, vtkIdType end)
{
T *rowPtr = this->Algo->Scalars + row*this->Algo->Inc1;
for ( ; row < end; ++row)
{
this->Algo->ProcessXEdge(this->Value, rowPtr, row);
rowPtr += this->Algo->Inc1;
}//for all rows in this batch
}
};
template <class T>
class vtkFlyingEdgesPass2
{
public:
vtkFlyingEdges2DAlgorithm<T> *Algo;
void operator()(vtkIdType row, vtkIdType end)
{
for ( ; row < end; ++row)
{
this->Algo->ProcessYEdges(row);
}//for all rows in this batch
}
};
template <class T>
class vtkFlyingEdgesPass3
{
public:
vtkFlyingEdges2DAlgorithm<T> *Algo;
double Value;
void operator()(vtkIdType row, vtkIdType end)
{
T *rowPtr = this->Algo->Scalars + row*this->Algo->Inc1;
for ( ; row < end; ++row)
{
this->Algo->GenerateOutput(this->Value, rowPtr, row);
rowPtr += this->Algo->Inc1;
}//for all rows in this batch
}
};
//----------------------------------------------------------------------------
// Contouring filter specialized for images. This templated function interfaces the
// vtkFlyingEdges2D class with the templated algorithm class. It also invokes
......@@ -586,7 +636,6 @@ void vtkContourImage(vtkFlyingEdges2D *self, T *scalars, vtkPoints *newPts,
vtkDataArray *newScalars, vtkCellArray *newLines,
vtkImageData *input, int *updateExt)
{
T *rowPtr;
double value, *values = self->GetValues();
int numContours = self->GetNumberOfContours();
vtkIdType vidx, row, *eMD;
......@@ -664,8 +713,9 @@ void vtkContourImage(vtkFlyingEdges2D *self, T *scalars, vtkPoints *newPts,
// Compute the starting location for scalar data. We may be operating
// on a part of the image.
scalars += incs[0]*(updateExt[0]-ext[0]) + incs[1]*(updateExt[2]-ext[2])
+ incs[2]*(updateExt[4]-ext[4]) + self->GetArrayComponent();
algo.Scalars = scalars + incs[0]*(updateExt[0]-ext[0]) +
incs[1]*(updateExt[2]-ext[2]) + incs[2]*(updateExt[4]-ext[4]) +
self->GetArrayComponent();
// The algorithm is separated into multiple passes. The first pass
// computes intersections on row edges, counting the number of intersected edges
......@@ -682,19 +732,17 @@ void vtkContourImage(vtkFlyingEdges2D *self, T *scalars, vtkPoints *newPts,
// PASS 1: Traverse all rows generating intersection points and building
// the case table. Also accumulate information necessary for later allocation.
// For example the number of output points is computed.
for (rowPtr=scalars, row=0; row < algo.Dims[1]; ++row)
{
algo.ProcessXEdge(value, rowPtr, row);
rowPtr += algo.Inc1;
}//for all rows
vtkFlyingEdgesPass1<T> pass1;
pass1.Algo = &algo;
pass1.Value = value;
vtkSMPTools::For(0,algo.Dims[1], pass1);
// PASS 2: Traverse all rows and process cell y edges. Continue building
// case table from y contributions (using computational trimming to reduce
// work) and keep track of cell y intersections.
for (row=0; row < (algo.Dims[1]-1); ++row)
{
algo.ProcessYEdges(row);
}//for all rows
vtkFlyingEdgesPass2<T> pass2;
pass2.Algo = &algo;
vtkSMPTools::For(0,algo.Dims[1]-1, pass2);
// PASS 3: Now allocate and generate output. First we have to update the
// x-Edge meta data to partition the output into separate pieces so
......@@ -731,11 +779,10 @@ void vtkContourImage(vtkFlyingEdges2D *self, T *scalars, vtkPoints *newPts,
}
// Now process each x-row and produce the output primitives.
for (rowPtr=scalars, row=0; row < (algo.Dims[1]-1); ++row)
{
algo.GenerateOutput(value, rowPtr, row);
rowPtr += algo.Inc1;
}//for all rows
vtkFlyingEdgesPass3<T> pass3;
pass3.Algo = &algo;
pass3.Value = value;
vtkSMPTools::For(0,algo.Dims[1]-1, pass3);
// Handle multiple contours
startXPts = numOutXPts;
......
......@@ -26,6 +26,7 @@
#include "vtkFloatArray.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkMarchingCubesTriangleCases.h"
#include "vtkSMPTools.h"
#include <math.h>
......@@ -894,6 +895,56 @@ GenerateOutput(double value, T* rowPtr, vtkIdType row, vtkIdType slice)
} //for all non-trimmed cells along this x-edge
}
//----------------------------------------------------------------------------
// Build threading integration with the SMPTools
template <class T> class vtkFlyingEdges3DPass1
{
public:
vtkFlyingEdges3DAlgorithm<T> *Algo;
double Value;
vtkIdType Slice;
T *SlicePtr;
void operator()(vtkIdType row, vtkIdType end)
{
T *rowPtr = this->SlicePtr + row*this->Algo->Inc1;
for ( ; row < end; ++row)
{
this->Algo->ProcessXEdge(this->Value, rowPtr, row, this->Slice);
rowPtr += this->Algo->Inc1;
}//for all rows in this batch
}
};
template <class T> class vtkFlyingEdges3DPass2
{
public:
vtkFlyingEdges3DAlgorithm<T> *Algo;
vtkIdType Slice;
void operator()(vtkIdType row, vtkIdType end)
{
for ( ; row < end; ++row)
{
this->Algo->ProcessYZEdges(row, this->Slice);
}//for all rows in this batch
}
};
template <class T> class vtkFlyingEdges3DPass3
{
public:
vtkFlyingEdges3DAlgorithm<T> *Algo;
double Value;
vtkIdType Slice;
T *SlicePtr;
void operator()(vtkIdType row, vtkIdType end)
{
T *rowPtr = this->SlicePtr + row*this->Algo->Inc1;
for ( ; row < end; ++row)
{
this->Algo->GenerateOutput(this->Value, rowPtr, row, this->Slice);
rowPtr += this->Algo->Inc1;
}//for all rows in this batch
}
};
//----------------------------------------------------------------------------
// Contouring filter specialized for 3D volumes. This templated function
// interfaces the vtkFlyingEdges3D class with the templated algorithm
......@@ -906,7 +957,7 @@ void ContourImage(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
{
double value, *values = self->GetValues();
int numContours = self->GetNumberOfContours();
T *rowPtr, *slicePtr;
T *slicePtr;
vtkIdType vidx, row, slice, *eMD, zInc;
vtkIdType numOutXPts, numOutYPts, numOutZPts, numOutTris;
vtkIdType numXPts=0, numYPts=0, numZPts=0, numTris=0;
......@@ -952,28 +1003,26 @@ void ContourImage(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
// intersections (i.e., accumulate information necessary for later output
// memory allocation, e.g., the number of output points along the x-rows
// are counted).
vtkFlyingEdges3DPass1<T> pass1;
pass1.Algo = &algo;
pass1.Value = value;
for (slicePtr=scalars, slice=0; slice < algo.Dims[2]; ++slice)
{
rowPtr = slicePtr;
for ( row=0; row < algo.Dims[1]; ++row)
{
algo.ProcessXEdge(value, rowPtr, row, slice);
rowPtr += algo.Inc1;
}//for all rows
pass1.Slice = slice;
pass1.SlicePtr = slicePtr;
vtkSMPTools::For(0,algo.Dims[1], pass1);
slicePtr += algo.Inc2;
}//for all slices
// PASS 2: Traverse all voxel x-rows and process voxel y&z edges. The
// result is a count of the number of y- and z-intersections, as well as
// the number of triangles generated along these voxel rows.
for (slicePtr=scalars, slice=0; slice < (algo.Dims[2]-1); ++slice)
vtkFlyingEdges3DPass2<T> pass2;
pass2.Algo = &algo;
for (slice=0; slice < (algo.Dims[2]-1); ++slice)
{
rowPtr = slicePtr;
for ( row=0; row < (algo.Dims[1]-1); ++row)
{
algo.ProcessYZEdges(row, slice);
}//for all rows
slicePtr += algo.Inc2;
pass2.Slice = slice;
vtkSMPTools::For(0,algo.Dims[1]-1, pass2);
}//for all slices
// PASS 3: Now allocate and generate output. First we have to update the
......@@ -1032,6 +1081,9 @@ void ContourImage(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
algo.NeedGradients = (algo.NewGradients || algo.NewNormals ? 1 : 0);
// Process voxel rows and generate output
vtkFlyingEdges3DPass3<T> pass3;
pass3.Algo = &algo;
pass3.Value = value;
vtkIdType *eMD0, *eMD1 = algo.EdgeMetaData;
for (slicePtr=scalars, slice=0; slice < (algo.Dims[2]-1); ++slice)
{
......@@ -1040,12 +1092,9 @@ void ContourImage(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
eMD1 = algo.EdgeMetaData + (slice+1)*6*algo.Dims[1];
if ( eMD1[3] > eMD0[3] ) //there are triangle primitives!
{
rowPtr = slicePtr;
for ( row=0; row < (algo.Dims[1]-1); ++row)
{
algo.GenerateOutput(value, rowPtr, row, slice);
rowPtr += algo.Inc1;
}//for all rows
pass3.SlicePtr = slicePtr;
pass3.Slice = slice;
vtkSMPTools::For(0,algo.Dims[1]-1, pass3);
}//if data to generate
slicePtr += algo.Inc2;
}//for all slices
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment