Non-recursive method to find cells in BoundingIntervalHierarchyExec
CUDA devices have problems with recursive algorithms that have no well- defined depth because the stack on a CUDA device tends to be pretty short. Fix the problem for BoundingIntervalHierarchyExec by changing to a state-machine based algorithm that follows the hierarchy up and down.
This commit is contained in:
parent
c463bbec93
commit
c008df90cc
@ -66,47 +66,126 @@ public:
|
|||||||
vtkm::Vec<vtkm::FloatDefault, 3>& parametric,
|
vtkm::Vec<vtkm::FloatDefault, 3>& parametric,
|
||||||
const vtkm::exec::FunctorBase& worklet) const override
|
const vtkm::exec::FunctorBase& worklet) const override
|
||||||
{
|
{
|
||||||
cellId = Find(0, point, parametric, worklet);
|
cellId = -1;
|
||||||
|
vtkm::Id nodeIndex = 0;
|
||||||
|
FindCellState state = FindCellState::EnterNode;
|
||||||
|
|
||||||
|
while ((cellId < 0) && !((nodeIndex == 0) && (state == FindCellState::AscendFromNode)))
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case FindCellState::EnterNode:
|
||||||
|
this->EnterNode(state, point, cellId, nodeIndex, parametric, worklet);
|
||||||
|
break;
|
||||||
|
case FindCellState::AscendFromNode:
|
||||||
|
this->AscendFromNode(state, nodeIndex);
|
||||||
|
break;
|
||||||
|
case FindCellState::DescendLeftChild:
|
||||||
|
this->DescendLeftChild(state, point, nodeIndex);
|
||||||
|
break;
|
||||||
|
case FindCellState::DescendRightChild:
|
||||||
|
this->DescendRightChild(state, point, nodeIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VTKM_EXEC vtkm::Id Find(vtkm::Id index,
|
enum struct FindCellState
|
||||||
const vtkm::Vec<vtkm::FloatDefault, 3>& point,
|
|
||||||
vtkm::Vec<vtkm::FloatDefault, 3>& parametric,
|
|
||||||
const vtkm::exec::FunctorBase& worklet) const
|
|
||||||
{
|
{
|
||||||
const vtkm::cont::BoundingIntervalHierarchyNode& node = Nodes.Get(index);
|
EnterNode,
|
||||||
|
AscendFromNode,
|
||||||
|
DescendLeftChild,
|
||||||
|
DescendRightChild
|
||||||
|
};
|
||||||
|
|
||||||
|
VTKM_EXEC
|
||||||
|
void EnterNode(FindCellState& state,
|
||||||
|
const vtkm::Vec<vtkm::FloatDefault, 3>& point,
|
||||||
|
vtkm::Id& cellId,
|
||||||
|
vtkm::Id nodeIndex,
|
||||||
|
vtkm::Vec<vtkm::FloatDefault, 3>& parametric,
|
||||||
|
const vtkm::exec::FunctorBase& worklet) const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(state == FindCellState::EnterNode);
|
||||||
|
|
||||||
|
const vtkm::cont::BoundingIntervalHierarchyNode& node = this->Nodes.Get(nodeIndex);
|
||||||
|
|
||||||
if (node.ChildIndex < 0)
|
if (node.ChildIndex < 0)
|
||||||
{
|
{
|
||||||
return FindInLeaf(point, parametric, node, worklet);
|
// In a leaf node. Look for a containing cell.
|
||||||
|
cellId = this->FindInLeaf(point, parametric, node, worklet);
|
||||||
|
state = FindCellState::AscendFromNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const vtkm::FloatDefault& c = point[node.Dimension];
|
state = FindCellState::DescendLeftChild;
|
||||||
vtkm::Id id1 = -1;
|
}
|
||||||
vtkm::Id id2 = -1;
|
}
|
||||||
if (c <= node.Node.LMax)
|
|
||||||
{
|
VTKM_EXEC
|
||||||
VTKM_ASSERT(Nodes.Get(node.ChildIndex).ParentIndex == index);
|
void AscendFromNode(FindCellState& state, vtkm::Id& nodeIndex) const
|
||||||
id1 = Find(node.ChildIndex, point, parametric, worklet);
|
{
|
||||||
}
|
VTKM_ASSERT(state == FindCellState::AscendFromNode);
|
||||||
if (id1 == -1 && c >= node.Node.RMin)
|
|
||||||
{
|
vtkm::Id childNodeIndex = nodeIndex;
|
||||||
VTKM_ASSERT(Nodes.Get(node.ChildIndex + 1).ParentIndex == index);
|
const vtkm::cont::BoundingIntervalHierarchyNode& childNode = this->Nodes.Get(childNodeIndex);
|
||||||
id2 = Find(node.ChildIndex + 1, point, parametric, worklet);
|
nodeIndex = childNode.ParentIndex;
|
||||||
}
|
const vtkm::cont::BoundingIntervalHierarchyNode& parentNode = this->Nodes.Get(nodeIndex);
|
||||||
if (id1 == -1 && id2 == -1)
|
|
||||||
{
|
if (parentNode.ChildIndex == childNodeIndex)
|
||||||
return -1;
|
{
|
||||||
}
|
// Ascending from left child. Descend into the right child.
|
||||||
else if (id1 == -1)
|
state = FindCellState::DescendRightChild;
|
||||||
{
|
}
|
||||||
return id2;
|
else
|
||||||
}
|
{
|
||||||
else
|
VTKM_ASSERT(parentNode.ChildIndex + 1 == childNodeIndex);
|
||||||
{
|
// Ascending from right child. Ascend again. (Don't need to change state.)
|
||||||
return id1;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC
|
||||||
|
void DescendLeftChild(FindCellState& state,
|
||||||
|
const vtkm::Vec<vtkm::FloatDefault, 3>& point,
|
||||||
|
vtkm::Id& nodeIndex) const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(state == FindCellState::DescendLeftChild);
|
||||||
|
|
||||||
|
const vtkm::cont::BoundingIntervalHierarchyNode& node = this->Nodes.Get(nodeIndex);
|
||||||
|
const vtkm::FloatDefault& coordinate = point[node.Dimension];
|
||||||
|
if (coordinate <= node.Node.LMax)
|
||||||
|
{
|
||||||
|
// Left child does contain the point. Do the actual descent.
|
||||||
|
nodeIndex = node.ChildIndex;
|
||||||
|
state = FindCellState::EnterNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Left child does not contain the point. Skip to the right child.
|
||||||
|
state = FindCellState::DescendRightChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC
|
||||||
|
void DescendRightChild(FindCellState& state,
|
||||||
|
const vtkm::Vec<vtkm::FloatDefault, 3>& point,
|
||||||
|
vtkm::Id& nodeIndex) const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(state == FindCellState::DescendRightChild);
|
||||||
|
|
||||||
|
const vtkm::cont::BoundingIntervalHierarchyNode& node = this->Nodes.Get(nodeIndex);
|
||||||
|
const vtkm::FloatDefault& coordinate = point[node.Dimension];
|
||||||
|
if (coordinate >= node.Node.RMin)
|
||||||
|
{
|
||||||
|
// Right child does contain the point. Do the actual descent.
|
||||||
|
nodeIndex = node.ChildIndex + 1;
|
||||||
|
state = FindCellState::EnterNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Right child does not contain the point. Skip to ascent
|
||||||
|
state = FindCellState::AscendFromNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user