vtk-m/vtkm/rendering/raytracing/CellIntersector.h
Sujin Philip e28309f09b Remove VTKM_EXEC_CONSTANT
If a global static array is declared with VTKM_EXEC_CONSTANT and the code
is compiled by nvcc (for multibackend code) then the array is only accesible
on the GPU. If for some reason a worklet fails on the cuda backend and it is
re-executed on any of the CPU backends, it will continue to fail.

We couldn't find a simple way to declare the array once and have it available
on both CPU and GPU. The approach we are using here is to declare the arrays
as static inside some "Get" function which is marked as VTKM_EXEC_CONT.
2017-12-05 13:49:55 -05:00

473 lines
16 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Cell_Intersector_h
#define vtk_m_rendering_raytracing_Cell_Intersector_h
#include <vtkm/rendering/raytracing/CellTables.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
//
// Any supported element. If the cell shape is not
// supported it does nothing, e.g. a 2D cellkk.
//
template <typename T>
VTKM_EXEC_CONT inline void IntersectZoo(T xpoints[8],
T ypoints[8],
T zpoints[8],
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6],
const vtkm::Int32& shapeType)
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
const vtkm::Int32 tableOffset =
CellTables::Get().ZooLookUp[CellTables::Get().CellTypeLookUp[shapeType]][0];
const vtkm::Int32 numTriangles =
CellTables::Get().ZooLookUp[CellTables::Get().CellTypeLookUp[shapeType]][1];
// Decompose each face into two triangles
for (int i = 0; i < 6; ++i)
distances[i] = -1.;
for (int i = 0; i < numTriangles; ++i)
{
const vtkm::Int32 offset = tableOffset + i;
vtkm::Vec<T, 3> a, c, b;
a[0] = xpoints[CellTables::Get().ZooTable[offset][1]];
a[1] = ypoints[CellTables::Get().ZooTable[offset][1]];
a[2] = zpoints[CellTables::Get().ZooTable[offset][1]];
b[0] = xpoints[CellTables::Get().ZooTable[offset][2]];
b[1] = ypoints[CellTables::Get().ZooTable[offset][2]];
b[2] = zpoints[CellTables::Get().ZooTable[offset][2]];
c[0] = xpoints[CellTables::Get().ZooTable[offset][3]];
c[1] = ypoints[CellTables::Get().ZooTable[offset][3]];
c[2] = zpoints[CellTables::Get().ZooTable[offset][3]];
const vtkm::Int32 faceId = CellTables::Get().ZooTable[offset][0];
T distance = -1.f;
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
{
if (distances[faceId] != -1.f)
distances[faceId] = vtkm::Min(distance, distances[faceId]);
else
distances[faceId] = distance;
}
}
}
template <typename T>
VTKM_EXEC_CONT inline void IntersectHex(T xpoints[8],
T ypoints[8],
T zpoints[8],
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
// Decompose each face into two triangles
for (int i = 0; i < 6; ++i)
{
vtkm::Vec<T, 3> a, c, b, d;
a[0] = xpoints[CellTables::Get().ShapesFaceList[i][1]];
a[1] = ypoints[CellTables::Get().ShapesFaceList[i][1]];
a[2] = zpoints[CellTables::Get().ShapesFaceList[i][1]];
b[0] = xpoints[CellTables::Get().ShapesFaceList[i][2]];
b[1] = ypoints[CellTables::Get().ShapesFaceList[i][2]];
b[2] = zpoints[CellTables::Get().ShapesFaceList[i][2]];
c[0] = xpoints[CellTables::Get().ShapesFaceList[i][3]];
c[1] = ypoints[CellTables::Get().ShapesFaceList[i][3]];
c[2] = zpoints[CellTables::Get().ShapesFaceList[i][3]];
d[0] = xpoints[CellTables::Get().ShapesFaceList[i][4]];
d[1] = ypoints[CellTables::Get().ShapesFaceList[i][4]];
d[2] = zpoints[CellTables::Get().ShapesFaceList[i][4]];
T distance = -1.f;
distances[i] = distance; //init to -1
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
distances[i] = distance;
distance = -1.f;
intersector.IntersectTriSn(a,
c,
d,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
{
if (distances[i] != -1.f)
distances[i] = vtkm::Min(distance, distances[i]);
else
distances[i] = distance;
}
}
}
template <typename T>
VTKM_EXEC_CONT inline void IntersectTet(T xpoints[8],
T ypoints[8],
T zpoints[8],
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
const vtkm::Int32 tableOffset =
CellTables::Get().FaceLookUp[CellTables::Get().CellTypeLookUp[CELL_SHAPE_TETRA]][0];
for (vtkm::Int32 i = 0; i < 4; ++i)
{
vtkm::Vec<T, 3> a, c, b;
a[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
a[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
a[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
b[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
b[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
b[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
c[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
c[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
c[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
T distance = -1.f;
distances[i] = distance; //init to -1
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
distances[i] = distance;
}
}
//
// Wedge
//
template <typename T>
VTKM_EXEC_CONT inline void IntersectWedge(T xpoints[8],
T ypoints[8],
T zpoints[8],
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
// TODO: try two sepate loops to see performance impact
const vtkm::Int32 tableOffset =
CellTables::Get().FaceLookUp[CellTables::Get().CellTypeLookUp[CELL_SHAPE_WEDGE]][0];
// Decompose each face into two triangles
for (int i = 0; i < 5; ++i)
{
vtkm::Vec<T, 3> a, c, b, d;
a[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
a[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
a[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][1]];
b[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
b[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
b[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][2]];
c[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
c[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
c[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][3]];
d[0] = xpoints[CellTables::Get().ShapesFaceList[i + tableOffset][4]];
d[1] = ypoints[CellTables::Get().ShapesFaceList[i + tableOffset][4]];
d[2] = zpoints[CellTables::Get().ShapesFaceList[i + tableOffset][4]];
T distance = -1.f;
distances[i] = distance; //init to -1
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
distances[i] = distance;
//
//First two faces are triangles
//
if (i < 2)
continue;
distance = -1.f;
intersector.IntersectTriSn(a,
c,
d,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
if (distance != -1.f)
{
if (distances[i] != -1.f)
distances[i] = vtkm::Min(distance, distances[i]);
else
distances[i] = distance;
}
}
}
//
// General Template should never be instantiated
//
template <int CellType>
class CellIntersector
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* vtkmNotUsed(xpoints),
T* vtkmNotUsed(ypoints),
T* vtkmNotUsed(zpoints),
const vtkm::Vec<T, 3>& vtkmNotUsed(dir),
const vtkm::Vec<T, 3>& vtkmNotUsed(origin),
T* vtkmNotUsed(distances),
const vtkm::UInt8 vtkmNotUsed(cellShape = 12));
};
//
// Hex Specialization
//
template <>
class CellIntersector<CELL_SHAPE_HEXAHEDRON>
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
T* ypoints,
T* zpoints,
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T* distances,
const vtkm::UInt8 cellShape = 12) const
{
if (cellShape == 12)
{
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
}
else
{
printf("CellIntersector Hex Error: unsupported cell type. Doing nothing\n");
}
}
};
//
//
// Hex Specialization Structured
//
template <>
class CellIntersector<254>
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
T* ypoints,
T* zpoints,
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T* distances,
const vtkm::UInt8 cellShape = 12) const
{
if (cellShape == 12)
{
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
}
else
{
printf("CellIntersector Hex Error: unsupported cell type. Doing nothing\n");
}
}
};
//
// Tet Specialization
//
template <>
class CellIntersector<CELL_SHAPE_TETRA>
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
T* ypoints,
T* zpoints,
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6],
const vtkm::UInt8 cellShape = 12) const
{
if (cellShape == CELL_SHAPE_TETRA)
{
IntersectTet(xpoints, ypoints, zpoints, dir, origin, distances);
}
else
{
printf("CellIntersector Tet Error: unsupported cell type. Doing nothing\n");
}
}
};
//
// Wedge Specialization
//
template <>
class CellIntersector<CELL_SHAPE_WEDGE>
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
T* ypoints,
T* zpoints,
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6],
const vtkm::UInt8 cellShape = 12) const
{
if (cellShape == CELL_SHAPE_WEDGE)
{
IntersectWedge(xpoints, ypoints, zpoints, dir, origin, distances);
}
else
{
printf("CellIntersector Wedge Error: unsupported cell type. Doing nothing\n");
}
}
};
//
// Zoo elements
//
template <>
class CellIntersector<255>
{
public:
template <typename T>
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
T* ypoints,
T* zpoints,
const vtkm::Vec<T, 3>& dir,
const vtkm::Vec<T, 3>& origin,
T distances[6],
const vtkm::UInt8 cellShape = 0) const
{
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
}
};
}
}
} // namespace vtkm::rendering::raytracing
#endif