Merge topic 'bvh/remove_device_template'

b03fec9a3 bvh device adpater banishment

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1559
This commit is contained in:
Matt Larsen 2019-02-26 02:33:30 +00:00 committed by Kitware Robot
commit 5e2e0d9ff1
2 changed files with 170 additions and 288 deletions

@ -27,7 +27,6 @@
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/AtomicArray.h>
@ -56,7 +55,6 @@ class LinearBVHBuilder
public:
class CountingIterator;
template <typename Device>
class GatherFloat32;
template <typename Device>
@ -66,23 +64,18 @@ public:
class BVHData;
template <typename Device>
class PropagateAABBs;
template <typename Device>
class TreeBuilder;
VTKM_CONT
LinearBVHBuilder() {}
template <typename Device>
VTKM_CONT void SortAABBS(BVHData& bvh, Device vtkmNotUsed(device), bool);
VTKM_CONT void SortAABBS(BVHData& bvh, bool);
template <typename Device>
VTKM_CONT void BuildHierarchy(BVHData& bvh);
template <typename Device>
VTKM_CONT void RunOnDevice(LinearBVH& linearBVH, Device device);
VTKM_CONT void Build(LinearBVH& linearBVH);
}; // class LinearBVHBuilder
class LinearBVHBuilder::CountingIterator : public vtkm::worklet::WorkletMapField
@ -96,31 +89,21 @@ public:
void operator()(const vtkm::Id& index, vtkm::Id& outId) const { outId = index; }
}; //class countingIterator
template <typename Device>
class LinearBVHBuilder::GatherFloat32 : public vtkm::worklet::WorkletMapField
{
private:
using FloatArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Float32>;
using PortalConst = typename FloatArrayHandle::ExecutionTypes<Device>::PortalConst;
using Portal = typename FloatArrayHandle::ExecutionTypes<Device>::Portal;
PortalConst InputPortal;
Portal OutputPortal;
public:
VTKM_CONT
GatherFloat32(const FloatArrayHandle& inputPortal,
FloatArrayHandle& outputPortal,
const vtkm::Id& size)
: InputPortal(inputPortal.PrepareForInput(Device()))
GatherFloat32() {}
using ControlSignature = void(FieldIn, WholeArrayIn, WholeArrayOut);
using ExecutionSignature = void(WorkIndex, _1, _2, _3);
template <typename InType, typename OutType>
VTKM_EXEC void operator()(const vtkm::Id& outIndex,
const vtkm::Id& inIndex,
const InType& inPortal,
OutType& outPortal) const
{
this->OutputPortal = outputPortal.PrepareForOutput(size, Device());
}
using ControlSignature = void(FieldIn);
using ExecutionSignature = void(WorkIndex, _1);
VTKM_EXEC
void operator()(const vtkm::Id& outIndex, const vtkm::Id& inIndex) const
{
OutputPortal.Set(outIndex, InputPortal.Get(inIndex));
outPortal.Set(outIndex, inPortal.Get(inIndex));
}
}; //class GatherFloat
@ -188,8 +171,7 @@ public:
vtkm::cont::ArrayHandleCounting<vtkm::Id> leafOffsets;
AABBs& AABB;
template <typename Device>
VTKM_CONT BVHData(vtkm::Id numPrimitives, AABBs& aabbs, Device vtkmNotUsed(device))
VTKM_CONT BVHData(vtkm::Id numPrimitives, AABBs& aabbs)
: leafOffsets(0, 2, numPrimitives)
, AABB(aabbs)
, NumPrimitives(numPrimitives)
@ -197,11 +179,11 @@ public:
InnerNodeCount = NumPrimitives - 1;
vtkm::Id size = NumPrimitives + InnerNodeCount;
parent.PrepareForOutput(size, Device());
leftChild.PrepareForOutput(InnerNodeCount, Device());
rightChild.PrepareForOutput(InnerNodeCount, Device());
innerBounds.PrepareForOutput(InnerNodeCount, Device());
mortonCodes.PrepareForOutput(NumPrimitives, Device());
parent.Allocate(size);
leftChild.Allocate(InnerNodeCount);
rightChild.Allocate(InnerNodeCount);
innerBounds.Allocate(InnerNodeCount);
mortonCodes.Allocate(NumPrimitives);
}
VTKM_CONT
@ -218,45 +200,17 @@ private:
}; // class BVH
template <typename Device>
class LinearBVHBuilder::PropagateAABBs : public vtkm::worklet::WorkletMapField
{
private:
using IdArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using Int8Handle = typename vtkm::cont::ArrayHandle<vtkm::Int8>;
using Float2ArrayHandle = typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 2>>;
using VecInt2Handle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 2>>;
using Float4ArrayHandle = typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 4>>;
using IdConstPortal = typename IdArrayHandle::ExecutionTypes<Device>::PortalConst;
using Float2ArrayPortal = typename Float2ArrayHandle::ExecutionTypes<Device>::Portal;
using Int2ArrayPortal = typename VecInt2Handle::ExecutionTypes<Device>::Portal;
using Int8ArrayPortal = typename Int8Handle::ExecutionTypes<Device>::Portal;
using Float4ArrayPortal = typename Float4ArrayHandle::ExecutionTypes<Device>::Portal;
Float4ArrayPortal FlatBVH;
IdConstPortal Parents;
IdConstPortal LeftChildren;
IdConstPortal RightChildren;
vtkm::Int32 LeafCount;
vtkm::exec::AtomicArrayExecutionObject<vtkm::Int32, Device> Counters;
public:
VTKM_CONT
PropagateAABBs(IdArrayHandle& parents,
IdArrayHandle& leftChildren,
IdArrayHandle& rightChildren,
vtkm::Int32 leafCount,
Float4ArrayHandle flatBVH,
const vtkm::cont::AtomicArray<vtkm::Int32>& counters)
: Parents(parents.PrepareForInput(Device()))
, LeftChildren(leftChildren.PrepareForInput(Device()))
, RightChildren(rightChildren.PrepareForInput(Device()))
, LeafCount(leafCount)
, Counters(counters.PrepareForExecution(Device()))
PropagateAABBs(vtkm::Int32 leafCount)
: LeafCount(leafCount)
{
this->FlatBVH = flatBVH.PrepareForOutput((LeafCount - 1) * 4, Device());
}
using ControlSignature = void(WholeArrayIn,
WholeArrayIn,
@ -264,10 +218,20 @@ public:
WholeArrayIn,
WholeArrayIn,
WholeArrayIn,
WholeArrayIn);
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4, _5, _6, _7);
WholeArrayIn,
WholeArrayIn, //Parents
WholeArrayIn, //lchild
WholeArrayIn, //rchild
AtomicArrayInOut, //counters
WholeArrayInOut // flatbvh
);
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12);
template <typename InputPortalType, typename OffsetPortalType>
template <typename InputPortalType,
typename OffsetPortalType,
typename IdPortalType,
typename AtomicType,
typename BVHType>
VTKM_EXEC_CONT void operator()(const vtkm::Id workIndex,
const InputPortalType& xmin,
const InputPortalType& ymin,
@ -275,21 +239,28 @@ public:
const InputPortalType& xmax,
const InputPortalType& ymax,
const InputPortalType& zmax,
const OffsetPortalType& leafOffsets) const
const OffsetPortalType& leafOffsets,
const IdPortalType& parents,
const IdPortalType& leftChildren,
const IdPortalType& rightChildren,
AtomicType& counters,
BVHType& flatBVH) const
{
//move up into the inner nodes
vtkm::Id currentNode = LeafCount - 1 + workIndex;
vtkm::Vec<vtkm::Id, 2> childVector;
while (currentNode != 0)
{
currentNode = Parents.Get(currentNode);
vtkm::Int32 oldCount = Counters.Add(currentNode, 1);
currentNode = parents.Get(currentNode);
vtkm::Int32 oldCount = counters.Add(currentNode, 1);
if (oldCount == 0)
{
return;
}
vtkm::Id currentNodeOffset = currentNode * 4;
childVector[0] = LeftChildren.Get(currentNode);
childVector[1] = RightChildren.Get(currentNode);
childVector[0] = leftChildren.Get(currentNode);
childVector[1] = rightChildren.Get(currentNode);
if (childVector[0] > (LeafCount - 2))
{
//our left child is a leaf, so just grab the AABB
@ -303,12 +274,12 @@ public:
first4Vec[1] = ymin.Get(childVector[0]);
first4Vec[2] = zmin.Get(childVector[0]);
first4Vec[3] = xmax.Get(childVector[0]);
FlatBVH.Set(currentNodeOffset, first4Vec);
flatBVH.Set(currentNodeOffset, first4Vec);
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
vtkm::Vec<vtkm::Float32, 4> second4Vec = flatBVH.Get(currentNodeOffset + 1);
second4Vec[0] = ymax.Get(childVector[0]);
second4Vec[1] = zmax.Get(childVector[0]);
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
flatBVH.Set(currentNodeOffset + 1, second4Vec);
// set index to leaf
vtkm::Id leafIndex = leafOffsets.Get(childVector[0]);
childVector[0] = -(leafIndex + 1);
@ -320,21 +291,21 @@ public:
//the current node left AABB.
vtkm::Id child = childVector[0] * 4;
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = flatBVH.Get(child);
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = flatBVH.Get(child + 1);
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = flatBVH.Get(child + 2);
cFirst4Vec[0] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
cFirst4Vec[1] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
cFirst4Vec[2] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
cFirst4Vec[3] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
FlatBVH.Set(currentNodeOffset, cFirst4Vec);
flatBVH.Set(currentNodeOffset, cFirst4Vec);
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
vtkm::Vec<vtkm::Float32, 4> second4Vec = flatBVH.Get(currentNodeOffset + 1);
second4Vec[0] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
second4Vec[1] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
flatBVH.Set(currentNodeOffset + 1, second4Vec);
}
if (childVector[1] > (LeafCount - 2))
@ -344,18 +315,18 @@ public:
childVector[1] = childVector[1] - LeafCount + 1;
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
vtkm::Vec<vtkm::Float32, 4> second4Vec = flatBVH.Get(currentNodeOffset + 1);
second4Vec[2] = xmin.Get(childVector[1]);
second4Vec[3] = ymin.Get(childVector[1]);
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
flatBVH.Set(currentNodeOffset + 1, second4Vec);
vtkm::Vec<vtkm::Float32, 4> third4Vec;
third4Vec[0] = zmin.Get(childVector[1]);
third4Vec[1] = xmax.Get(childVector[1]);
third4Vec[2] = ymax.Get(childVector[1]);
third4Vec[3] = zmax.Get(childVector[1]);
FlatBVH.Set(currentNodeOffset + 2, third4Vec);
flatBVH.Set(currentNodeOffset + 2, third4Vec);
// set index to leaf
vtkm::Id leafIndex = leafOffsets.Get(childVector[1]);
@ -368,20 +339,20 @@ public:
//the current node left AABB.
vtkm::Id child = childVector[1] * 4;
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = flatBVH.Get(child);
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = flatBVH.Get(child + 1);
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = flatBVH.Get(child + 2);
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
vtkm::Vec<vtkm::Float32, 4> second4Vec = flatBVH.Get(currentNodeOffset + 1);
second4Vec[2] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
second4Vec[3] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
flatBVH.Set(currentNodeOffset + 1, second4Vec);
cThird4Vec[0] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
cThird4Vec[1] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
cThird4Vec[2] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
cThird4Vec[3] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
FlatBVH.Set(currentNodeOffset + 2, cThird4Vec);
flatBVH.Set(currentNodeOffset + 2, cThird4Vec);
}
vtkm::Vec<vtkm::Float32, 4> fourth4Vec;
vtkm::Int32 leftChild =
@ -390,23 +361,14 @@ public:
vtkm::Int32 rightChild =
static_cast<vtkm::Int32>((childVector[1] >= 0) ? childVector[1] * 4 : childVector[1]);
memcpy(&fourth4Vec[1], &rightChild, 4);
FlatBVH.Set(currentNodeOffset + 3, fourth4Vec);
flatBVH.Set(currentNodeOffset + 3, fourth4Vec);
}
}
}; //class PropagateAABBs
template <typename Device>
class LinearBVHBuilder::TreeBuilder : public vtkm::worklet::WorkletMapField
{
public:
using UIntArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::UInt32>;
using IdArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using UIntPortalType = typename UIntArrayHandle::ExecutionTypes<Device>::PortalConst;
using IdPortalType = typename IdArrayHandle::ExecutionTypes<Device>::Portal;
private:
UIntPortalType MortonCodePortal;
IdPortalType ParentPortal;
vtkm::Id LeafCount;
vtkm::Id InnerCount;
//TODO: get intrinsic support
@ -451,15 +413,17 @@ private:
//
// returns count of the largest binary prefix
VTKM_EXEC
inline vtkm::Int32 delta(const vtkm::Int32& a, const vtkm::Int32& b) const
template <typename MortonType>
VTKM_EXEC inline vtkm::Int32 delta(const vtkm::Int32& a,
const vtkm::Int32& b,
const MortonType& mortonCodePortal) const
{
bool tie = false;
bool outOfRange = (b < 0 || b > LeafCount - 1);
//still make the call but with a valid adderss
vtkm::Int32 bb = (outOfRange) ? 0 : b;
vtkm::UInt32 aCode = MortonCodePortal.Get(a);
vtkm::UInt32 bCode = MortonCodePortal.Get(bb);
vtkm::UInt32 aCode = mortonCodePortal.Get(a);
vtkm::UInt32 bCode = mortonCodePortal.Get(bb);
//use xor to find where they differ
vtkm::UInt32 exOr = aCode ^ bCode;
tie = (exOr == 0);
@ -474,48 +438,49 @@ private:
public:
VTKM_CONT
TreeBuilder(const UIntArrayHandle& mortonCodesHandle,
IdArrayHandle& parentHandle,
const vtkm::Id& leafCount)
: MortonCodePortal(mortonCodesHandle.PrepareForInput(Device()))
, LeafCount(leafCount)
TreeBuilder(const vtkm::Id& leafCount)
: LeafCount(leafCount)
, InnerCount(leafCount - 1)
{
InnerCount = LeafCount - 1;
this->ParentPortal = parentHandle.PrepareForOutput(InnerCount + LeafCount, Device());
}
using ControlSignature = void(FieldOut, FieldOut);
using ExecutionSignature = void(WorkIndex, _1, _2);
VTKM_EXEC
void operator()(const vtkm::Id& index, vtkm::Id& leftChild, vtkm::Id& rightChild) const
using ControlSignature = void(FieldOut, FieldOut, WholeArrayIn, WholeArrayOut);
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4);
template <typename MortonType, typename ParentType>
VTKM_EXEC void operator()(const vtkm::Id& index,
vtkm::Id& leftChild,
vtkm::Id& rightChild,
const MortonType& mortonCodePortal,
ParentType& parentPortal) const
{
vtkm::Int32 idx = vtkm::Int32(index);
//something = MortonCodePortal.Get(index) + 1;
//determine range direction
vtkm::Int32 d = 0 > (delta(idx, idx + 1) - delta(idx, idx - 1)) ? -1 : 1;
vtkm::Int32 d =
0 > (delta(idx, idx + 1, mortonCodePortal) - delta(idx, idx - 1, mortonCodePortal)) ? -1 : 1;
//find upper bound for the length of the range
vtkm::Int32 minDelta = delta(idx, idx - d);
vtkm::Int32 minDelta = delta(idx, idx - d, mortonCodePortal);
vtkm::Int32 lMax = 2;
while (delta(idx, idx + lMax * d) > minDelta)
while (delta(idx, idx + lMax * d, mortonCodePortal) > minDelta)
lMax *= 2;
//binary search to find the lower bound
vtkm::Int32 l = 0;
for (int t = lMax / 2; t >= 1; t /= 2)
{
if (delta(idx, idx + (l + t) * d) > minDelta)
if (delta(idx, idx + (l + t) * d, mortonCodePortal) > minDelta)
l += t;
}
vtkm::Int32 j = idx + l * d;
vtkm::Int32 deltaNode = delta(idx, j);
vtkm::Int32 deltaNode = delta(idx, j, mortonCodePortal);
vtkm::Int32 s = 0;
vtkm::Float32 divFactor = 2.f;
//find the split position using a binary search
for (vtkm::Int32 t = (vtkm::Int32)ceil(vtkm::Float32(l) / divFactor);;
divFactor *= 2, t = (vtkm::Int32)ceil(vtkm::Float32(l) / divFactor))
{
if (delta(idx, idx + (s + t) * d) > deltaNode)
if (delta(idx, idx + (s + t) * d, mortonCodePortal) > deltaNode)
{
s += t;
}
@ -529,13 +494,13 @@ public:
if (vtkm::Min(idx, j) == split)
{
//leaf
ParentPortal.Set(split + InnerCount, idx);
parentPortal.Set(split + InnerCount, idx);
leftChild = split + InnerCount;
}
else
{
//inner node
ParentPortal.Set(split, idx);
parentPortal.Set(split, idx);
leftChild = split;
}
@ -543,77 +508,76 @@ public:
if (vtkm::Max(idx, j) == split + 1)
{
//leaf
ParentPortal.Set(split + InnerCount + 1, idx);
parentPortal.Set(split + InnerCount + 1, idx);
rightChild = split + InnerCount + 1;
}
else
{
ParentPortal.Set(split + 1, idx);
parentPortal.Set(split + 1, idx);
rightChild = split + 1;
}
}
}; // class TreeBuilder
template <typename Device>
VTKM_CONT void LinearBVHBuilder::SortAABBS(BVHData& bvh, Device device, bool singleAABB)
VTKM_CONT void LinearBVHBuilder::SortAABBS(BVHData& bvh, bool singleAABB)
{
vtkm::worklet::Invoker invoke(device);
//create array of indexes to be sorted with morton codes
vtkm::cont::ArrayHandle<vtkm::Id> iterator;
iterator.PrepareForOutput(bvh.GetNumberOfPrimitives(), device);
invoke(CountingIterator{}, iterator);
iterator.Allocate(bvh.GetNumberOfPrimitives());
vtkm::worklet::DispatcherMapField<CountingIterator> iterDispatcher;
iterDispatcher.Invoke(iterator);
//sort the morton codes
vtkm::cont::DeviceAdapterAlgorithm<Device>::SortByKey(bvh.mortonCodes, iterator);
vtkm::cont::Algorithm::SortByKey(bvh.mortonCodes, iterator);
vtkm::Id arraySize = bvh.GetNumberOfPrimitives();
vtkm::cont::ArrayHandle<vtkm::Float32> temp1;
vtkm::cont::ArrayHandle<vtkm::Float32> temp2;
temp1.Allocate(arraySize);
vtkm::worklet::DispatcherMapField<GatherFloat32> gatherDispatcher;
//tempStorage = new vtkm::cont::ArrayHandle<vtkm::Float32>();
//xmins
invoke(GatherFloat32<Device>{ bvh.AABB.xmins, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.xmins, temp1);
temp2 = bvh.AABB.xmins;
bvh.AABB.xmins = temp1;
temp1 = temp2;
//ymins
invoke(GatherFloat32<Device>{ bvh.AABB.ymins, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.ymins, temp1);
temp2 = bvh.AABB.ymins;
bvh.AABB.ymins = temp1;
temp1 = temp2;
//zmins
invoke(GatherFloat32<Device>{ bvh.AABB.zmins, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.zmins, temp1);
temp2 = bvh.AABB.zmins;
bvh.AABB.zmins = temp1;
temp1 = temp2;
//xmaxs
invoke(GatherFloat32<Device>{ bvh.AABB.xmaxs, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.xmaxs, temp1);
temp2 = bvh.AABB.xmaxs;
bvh.AABB.xmaxs = temp1;
temp1 = temp2;
//ymaxs
invoke(GatherFloat32<Device>{ bvh.AABB.ymaxs, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.ymaxs, temp1);
temp2 = bvh.AABB.ymaxs;
bvh.AABB.ymaxs = temp1;
temp1 = temp2;
//zmaxs
invoke(GatherFloat32<Device>{ bvh.AABB.zmaxs, temp1, arraySize }, iterator);
gatherDispatcher.Invoke(iterator, bvh.AABB.zmaxs, temp1);
temp2 = bvh.AABB.zmaxs;
bvh.AABB.zmaxs = temp1;
temp1 = temp2;
// Create the leaf references
bvh.leafs.PrepareForOutput(arraySize * 2, Device());
bvh.leafs.Allocate(arraySize * 2);
// we only actually have a single primitive, but the algorithm
// requires 2. Make sure they both point to the original
// primitive
@ -625,24 +589,15 @@ VTKM_CONT void LinearBVHBuilder::SortAABBS(BVHData& bvh, Device device, bool sin
iterPortal.Set(i, 0);
}
}
invoke(CreateLeafs{}, iterator, bvh.leafs);
vtkm::worklet::DispatcherMapField<CreateLeafs> leafDispatcher;
leafDispatcher.Invoke(iterator, bvh.leafs);
} // method SortAABB
// Adding this as a template parameter to allow restricted types and
// storage for dynamic coordinate system to limit crazy code bloat and
// compile times.
//
template <typename Device>
VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device)
VTKM_CONT void LinearBVHBuilder::Build(LinearBVH& linearBVH)
{
vtkm::worklet::Invoker invoke(device);
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("bvh_constuct");
vtkm::cont::Timer constructTimer{ Device() };
constructTimer.Start();
//
//
// This algorithm needs at least 2 AABBs
@ -678,30 +633,20 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
}
logger->AddLogData("bvh_num_aabbs", numberOfAABBs);
const vtkm::Id numBBoxes = numberOfAABBs;
BVHData bvh(numBBoxes, linearBVH.GetAABBs(), device);
BVHData bvh(numBBoxes, linearBVH.GetAABBs());
vtkm::cont::Timer timer{ Device() };
timer.Start();
// Find the extent of all bounding boxes to generate normalization for morton codes
vtkm::Vec<vtkm::Float32, 3> minExtent(vtkm::Infinity32(), vtkm::Infinity32(), vtkm::Infinity32());
vtkm::Vec<vtkm::Float32, 3> maxExtent(
vtkm::NegativeInfinity32(), vtkm::NegativeInfinity32(), vtkm::NegativeInfinity32());
maxExtent[0] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.xmaxs, maxExtent[0], MaxValue());
maxExtent[1] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.ymaxs, maxExtent[1], MaxValue());
maxExtent[2] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.zmaxs, maxExtent[2], MaxValue());
minExtent[0] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.xmins, minExtent[0], MinValue());
minExtent[1] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.ymins, minExtent[1], MinValue());
minExtent[2] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.zmins, minExtent[2], MinValue());
maxExtent[0] = vtkm::cont::Algorithm::Reduce(bvh.AABB.xmaxs, maxExtent[0], MaxValue());
maxExtent[1] = vtkm::cont::Algorithm::Reduce(bvh.AABB.ymaxs, maxExtent[1], MaxValue());
maxExtent[2] = vtkm::cont::Algorithm::Reduce(bvh.AABB.zmaxs, maxExtent[2], MaxValue());
minExtent[0] = vtkm::cont::Algorithm::Reduce(bvh.AABB.xmins, minExtent[0], MinValue());
minExtent[1] = vtkm::cont::Algorithm::Reduce(bvh.AABB.ymins, minExtent[1], MinValue());
minExtent[2] = vtkm::cont::Algorithm::Reduce(bvh.AABB.zmins, minExtent[2], MinValue());
linearBVH.TotalBounds.X.Min = minExtent[0];
linearBVH.TotalBounds.X.Max = maxExtent[0];
@ -710,10 +655,6 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
linearBVH.TotalBounds.Z.Min = minExtent[2];
linearBVH.TotalBounds.Z.Max = maxExtent[2];
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("calc_extents", time);
timer.Start();
vtkm::Vec<vtkm::Float32, 3> deltaExtent = maxExtent - minExtent;
vtkm::Vec<vtkm::Float32, 3> inverseExtent;
for (int i = 0; i < 3; ++i)
@ -722,82 +663,50 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
}
//Generate the morton codes
invoke(MortonCodeAABB{ inverseExtent, minExtent },
bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.mortonCodes);
vtkm::worklet::DispatcherMapField<MortonCodeAABB> mortonDispatch(
MortonCodeAABB(inverseExtent, minExtent));
mortonDispatch.Invoke(bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.mortonCodes);
linearBVH.Allocate(bvh.GetNumberOfPrimitives());
time = timer.GetElapsedTime();
logger->AddLogData("morton_codes", time);
timer.Start();
SortAABBS(bvh, singleAABB);
linearBVH.Allocate(bvh.GetNumberOfPrimitives(), device);
SortAABBS(bvh, device, singleAABB);
time = timer.GetElapsedTime();
logger->AddLogData("sort_aabbs", time);
timer.Start();
invoke(TreeBuilder<Device>{ bvh.mortonCodes, bvh.parent, bvh.GetNumberOfPrimitives() },
bvh.leftChild,
bvh.rightChild);
time = timer.GetElapsedTime();
logger->AddLogData("build_tree", time);
timer.Start();
vtkm::worklet::DispatcherMapField<TreeBuilder> treeDispatch(
TreeBuilder(bvh.GetNumberOfPrimitives()));
treeDispatch.Invoke(bvh.leftChild, bvh.rightChild, bvh.mortonCodes, bvh.parent);
const vtkm::Int32 primitiveCount = vtkm::Int32(bvh.GetNumberOfPrimitives());
vtkm::cont::ArrayHandle<vtkm::Int32> counters;
counters.PrepareForOutput(bvh.GetNumberOfPrimitives() - 1, device);
counters.Allocate(bvh.GetNumberOfPrimitives() - 1);
vtkm::cont::ArrayHandleConstant<vtkm::Int32> zero(0, bvh.GetNumberOfPrimitives() - 1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(zero, counters);
vtkm::cont::Algorithm::Copy(zero, counters);
vtkm::cont::AtomicArray<vtkm::Int32> atomicCounters(counters);
vtkm::worklet::DispatcherMapField<PropagateAABBs> propDispatch(PropagateAABBs{ primitiveCount });
PropagateAABBs<Device> propagateWorklet(
bvh.parent, bvh.leftChild, bvh.rightChild, primitiveCount, linearBVH.FlatBVH, atomicCounters);
invoke(propagateWorklet,
bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.leafOffsets);
propDispatch.Invoke(bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.leafOffsets,
bvh.parent,
bvh.leftChild,
bvh.rightChild,
counters,
linearBVH.FlatBVH);
linearBVH.Leafs = bvh.leafs;
time = timer.GetElapsedTime();
logger->AddLogData("propagate_aabbs", time);
time = constructTimer.GetElapsedTime();
logger->CloseLogEntry(time);
}
} //namespace detail
struct LinearBVH::ConstructFunctor
{
LinearBVH* Self;
VTKM_CONT
ConstructFunctor(LinearBVH* self)
: Self(self)
{
}
template <typename Device>
bool operator()(Device)
{
Self->ConstructOnDevice(Device());
return true;
}
};
LinearBVH::LinearBVH()
: IsConstructed(false)
, CanConstruct(false){};
@ -820,11 +729,11 @@ LinearBVH::LinearBVH(const LinearBVH& other)
, CanConstruct(other.CanConstruct)
{
}
template <typename Device>
VTKM_CONT void LinearBVH::Allocate(const vtkm::Id& leafCount, Device deviceAdapter)
VTKM_CONT void LinearBVH::Allocate(const vtkm::Id& leafCount)
{
LeafCount = leafCount;
FlatBVH.PrepareForOutput((leafCount - 1) * 4, deviceAdapter);
FlatBVH.Allocate((leafCount - 1) * 4);
}
void LinearBVH::Construct()
@ -835,9 +744,8 @@ void LinearBVH::Construct()
throw vtkm::cont::ErrorBadValue(
"Linear BVH: coordinates and triangles must be set before calling construct!");
ConstructFunctor functor(this);
vtkm::cont::TryExecute(functor);
IsConstructed = true;
detail::LinearBVHBuilder builder;
builder.Build(*this);
}
VTKM_CONT
@ -848,43 +756,22 @@ void LinearBVH::SetData(AABBs& aabbs)
CanConstruct = true;
}
template <typename Device>
void LinearBVH::ConstructOnDevice(Device device)
{
Logger* logger = Logger::GetInstance();
vtkm::cont::Timer timer{ Device() };
timer.Start();
logger->OpenLogEntry("bvh");
if (!CanConstruct)
throw vtkm::cont::ErrorBadValue(
"Linear BVH: coordinates and triangles must be set before calling construct!");
if (!IsConstructed)
{
detail::LinearBVHBuilder builder;
builder.RunOnDevice(*this, device);
IsConstructed = true;
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
// explicitly export
template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<
vtkm::cont::DeviceAdapterTagSerial>(vtkm::cont::DeviceAdapterTagSerial);
#ifdef VTKM_ENABLE_TBB
template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagTBB>(
vtkm::cont::DeviceAdapterTagTBB);
#endif
#ifdef VTKM_ENABLE_OPENMP
template VTKM_CONT_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagOpenMP>(
vtkm::cont::DeviceAdapterTagOpenMP);
#endif
#ifdef VTKM_ENABLE_CUDA
template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagCuda>(
vtkm::cont::DeviceAdapterTagCuda);
#endif
//template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<
// vtkm::cont::DeviceAdapterTagSerial>(vtkm::cont::DeviceAdapterTagSerial);
//#ifdef VTKM_ENABLE_TBB
//template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagTBB>(
// vtkm::cont::DeviceAdapterTagTBB);
//#endif
//#ifdef VTKM_ENABLE_OPENMP
//template VTKM_CONT_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagOpenMP>(
// vtkm::cont::DeviceAdapterTagOpenMP);
//#endif
//#ifdef VTKM_ENABLE_CUDA
//template VTKM_RENDERING_EXPORT void LinearBVH::ConstructOnDevice<vtkm::cont::DeviceAdapterTagCuda>(
// vtkm::cont::DeviceAdapterTagCuda);
//#endif
//
VTKM_CONT
bool LinearBVH::GetIsConstructed() const
{
@ -893,7 +780,7 @@ bool LinearBVH::GetIsConstructed() const
vtkm::Id LinearBVH::GetNumberOfAABBs() const
{
return AABB.xmins.GetPortalConstControl().GetNumberOfValues();
return AABB.xmins.GetNumberOfValues();
}
AABBs& LinearBVH::GetAABBs()

@ -53,7 +53,6 @@ public:
InnerNodesHandle FlatBVH;
LeafNodesHandle Leafs;
vtkm::Bounds TotalBounds;
struct ConstructFunctor;
vtkm::Id LeafCount;
protected:
@ -69,8 +68,7 @@ public:
VTKM_CONT
LinearBVH(const LinearBVH& other);
template <typename DeviceAdapter>
VTKM_CONT void Allocate(const vtkm::Id& leafCount, DeviceAdapter deviceAdapter);
VTKM_CONT void Allocate(const vtkm::Id& leafCount);
VTKM_CONT
void Construct();
@ -81,9 +79,6 @@ public:
VTKM_CONT
AABBs& GetAABBs();
template <typename Device>
VTKM_CONT void ConstructOnDevice(Device device);
VTKM_CONT
bool GetIsConstructed() const;