1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 #include <sstream>
11 #include <vtkm/CellShape.h>
12 #include <vtkm/cont/ErrorBadValue.h>
13 #include <vtkm/cont/Timer.h>
14 #include <vtkm/cont/internal/DeviceAdapterListHelpers.h>
15 #include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
16 #include <vtkm/rendering/raytracing/Logger.h>
17 #include <vtkm/rendering/raytracing/MeshConnectivityBase.h>
18 #include <vtkm/rendering/raytracing/MeshConnectivityContainers.h>
19 #include <vtkm/rendering/raytracing/Ray.h>
20 #include <vtkm/rendering/raytracing/TriangleIntersector.h>
21 namespace vtkm
22 {
23 namespace rendering
24 {
25 namespace raytracing
26 {
27 
MeshConnContainer()28 MeshConnContainer::MeshConnContainer(){};
~MeshConnContainer()29 MeshConnContainer::~MeshConnContainer(){};
30 
31 template <typename T>
FindEntryImpl(Ray<T> & rays)32 VTKM_CONT void MeshConnContainer::FindEntryImpl(Ray<T>& rays)
33 {
34   bool getCellIndex = true;
35 
36   Intersector.SetUseWaterTight(true);
37 
38   Intersector.IntersectRays(rays, getCellIndex);
39 }
40 
PrepareForExecution(const vtkm::cont::DeviceAdapterId deviceId,vtkm::cont::Token & token)41 MeshWrapper MeshConnContainer::PrepareForExecution(const vtkm::cont::DeviceAdapterId deviceId,
42                                                    vtkm::cont::Token& token)
43 {
44   return MeshWrapper(const_cast<MeshConnectivityBase*>(this->Construct(deviceId, token)));
45 }
46 
FindEntry(Ray<vtkm::Float32> & rays)47 void MeshConnContainer::FindEntry(Ray<vtkm::Float32>& rays)
48 {
49   this->FindEntryImpl(rays);
50 }
51 
FindEntry(Ray<vtkm::Float64> & rays)52 void MeshConnContainer::FindEntry(Ray<vtkm::Float64>& rays)
53 {
54   this->FindEntryImpl(rays);
55 }
56 
57 VTKM_CONT
UnstructuredContainer(const vtkm::cont::CellSetExplicit<> & cellset,const vtkm::cont::CoordinateSystem & coords,IdHandle & faceConn,IdHandle & faceOffsets,Id4Handle & triangles)58 UnstructuredContainer::UnstructuredContainer(const vtkm::cont::CellSetExplicit<>& cellset,
59                                              const vtkm::cont::CoordinateSystem& coords,
60                                              IdHandle& faceConn,
61                                              IdHandle& faceOffsets,
62                                              Id4Handle& triangles)
63   : FaceConnectivity(faceConn)
64   , FaceOffsets(faceOffsets)
65   , Cellset(cellset)
66   , Coords(coords)
67 {
68   this->Triangles = triangles;
69   //
70   // Grab the cell arrays
71   //
72   CellConn =
73     Cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
74   CellOffsets =
75     Cellset.GetOffsetsArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
76   Shapes = Cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
77 
78   Intersector.SetData(Coords, Triangles);
79 }
80 
~UnstructuredContainer()81 UnstructuredContainer::~UnstructuredContainer(){};
82 
Construct(const vtkm::cont::DeviceAdapterId deviceId,vtkm::cont::Token & token)83 const MeshConnectivityBase* UnstructuredContainer::Construct(
84   const vtkm::cont::DeviceAdapterId deviceId,
85   vtkm::cont::Token& token)
86 {
87   switch (deviceId.GetValue())
88   {
89 #ifdef VTKM_ENABLE_OPENMP
90     case VTKM_DEVICE_ADAPTER_OPENMP:
91       using OMP = vtkm::cont::DeviceAdapterTagOpenMP;
92       {
93         MeshConnUnstructured<OMP> conn(this->FaceConnectivity,
94                                        this->FaceOffsets,
95                                        this->CellConn,
96                                        this->CellOffsets,
97                                        this->Shapes,
98                                        token);
99         Handle = make_MeshConnHandle(conn);
100       }
101       return Handle.PrepareForExecution(OMP(), token);
102 #endif
103 #ifdef VTKM_ENABLE_TBB
104     case VTKM_DEVICE_ADAPTER_TBB:
105       using TBB = vtkm::cont::DeviceAdapterTagTBB;
106       {
107         MeshConnUnstructured<TBB> conn(this->FaceConnectivity,
108                                        this->FaceOffsets,
109                                        this->CellConn,
110                                        this->CellOffsets,
111                                        this->Shapes,
112                                        token);
113         Handle = make_MeshConnHandle(conn);
114       }
115       return Handle.PrepareForExecution(TBB(), token);
116 #endif
117 #ifdef VTKM_ENABLE_CUDA
118     case VTKM_DEVICE_ADAPTER_CUDA:
119       using CUDA = vtkm::cont::DeviceAdapterTagCuda;
120       {
121         MeshConnUnstructured<CUDA> conn(this->FaceConnectivity,
122                                         this->FaceOffsets,
123                                         this->CellConn,
124                                         this->CellOffsets,
125                                         this->Shapes,
126                                         token);
127         Handle = make_MeshConnHandle(conn);
128       }
129       return Handle.PrepareForExecution(CUDA(), token);
130 #endif
131 #ifdef VTKM_ENABLE_KOKKOS
132     case VTKM_DEVICE_ADAPTER_KOKKOS:
133       using KOKKOS = vtkm::cont::DeviceAdapterTagKokkos;
134       {
135         MeshConnUnstructured<KOKKOS> conn(this->FaceConnectivity,
136                                           this->FaceOffsets,
137                                           this->CellConn,
138                                           this->CellOffsets,
139                                           this->Shapes,
140                                           token);
141         Handle = make_MeshConnHandle(conn);
142       }
143       return Handle.PrepareForExecution(KOKKOS(), token);
144 #endif
145     case VTKM_DEVICE_ADAPTER_SERIAL:
146       VTKM_FALLTHROUGH;
147     default:
148       using SERIAL = vtkm::cont::DeviceAdapterTagSerial;
149       {
150         MeshConnUnstructured<SERIAL> conn(this->FaceConnectivity,
151                                           this->FaceOffsets,
152                                           this->CellConn,
153                                           this->CellOffsets,
154                                           this->Shapes,
155                                           token);
156         Handle = make_MeshConnHandle(conn);
157       }
158       return Handle.PrepareForExecution(SERIAL(), token);
159   }
160 }
161 
162 VTKM_CONT
UnstructuredSingleContainer()163 UnstructuredSingleContainer::UnstructuredSingleContainer() {}
164 
165 VTKM_CONT
UnstructuredSingleContainer(const vtkm::cont::CellSetSingleType<> & cellset,const vtkm::cont::CoordinateSystem & coords,IdHandle & faceConn,Id4Handle & triangles)166 UnstructuredSingleContainer::UnstructuredSingleContainer(
167   const vtkm::cont::CellSetSingleType<>& cellset,
168   const vtkm::cont::CoordinateSystem& coords,
169   IdHandle& faceConn,
170   Id4Handle& triangles)
171   : FaceConnectivity(faceConn)
172   , Coords(coords)
173   , Cellset(cellset)
174 {
175 
176   this->Triangles = triangles;
177 
178   this->Intersector.SetUseWaterTight(true);
179 
180   CellConnectivity =
181     Cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
182   vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
183     Cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
184 
185   ShapeId = shapes.ReadPortal().Get(0);
186   CellTables tables;
187   NumIndices = tables.FaceLookUp(tables.CellTypeLookUp(ShapeId), 2);
188 
189   if (NumIndices == 0)
190   {
191     std::stringstream message;
192     message << "Unstructured Mesh Connecitity Single type Error: unsupported cell type: ";
193     message << ShapeId;
194     throw vtkm::cont::ErrorBadValue(message.str());
195   }
196   vtkm::Id start = 0;
197   NumFaces = tables.FaceLookUp(tables.CellTypeLookUp(ShapeId), 1);
198   vtkm::Id numCells = CellConnectivity.ReadPortal().GetNumberOfValues();
199   CellOffsets = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start, NumIndices, numCells);
200 
201   Logger* logger = Logger::GetInstance();
202   logger->OpenLogEntry("mesh_conn_construction");
203 
204   Intersector.SetData(Coords, Triangles);
205 }
206 
Construct(const vtkm::cont::DeviceAdapterId deviceId,vtkm::cont::Token & token)207 const MeshConnectivityBase* UnstructuredSingleContainer::Construct(
208   const vtkm::cont::DeviceAdapterId deviceId,
209   vtkm::cont::Token& token)
210 {
211   switch (deviceId.GetValue())
212   {
213 #ifdef VTKM_ENABLE_OPENMP
214     case VTKM_DEVICE_ADAPTER_OPENMP:
215       using OMP = vtkm::cont::DeviceAdapterTagOpenMP;
216       {
217         MeshConnSingleType<OMP> conn(this->FaceConnectivity,
218                                      this->CellConnectivity,
219                                      this->CellOffsets,
220                                      this->ShapeId,
221                                      this->NumIndices,
222                                      this->NumFaces,
223                                      token);
224         Handle = make_MeshConnHandle(conn);
225       }
226       return Handle.PrepareForExecution(OMP(), token);
227 #endif
228 #ifdef VTKM_ENABLE_TBB
229     case VTKM_DEVICE_ADAPTER_TBB:
230       using TBB = vtkm::cont::DeviceAdapterTagTBB;
231       {
232         MeshConnSingleType<TBB> conn(this->FaceConnectivity,
233                                      this->CellConnectivity,
234                                      this->CellOffsets,
235                                      this->ShapeId,
236                                      this->NumIndices,
237                                      this->NumFaces,
238                                      token);
239         Handle = make_MeshConnHandle(conn);
240       }
241       return Handle.PrepareForExecution(TBB(), token);
242 #endif
243 #ifdef VTKM_ENABLE_CUDA
244     case VTKM_DEVICE_ADAPTER_CUDA:
245       using CUDA = vtkm::cont::DeviceAdapterTagCuda;
246       {
247         MeshConnSingleType<CUDA> conn(this->FaceConnectivity,
248                                       this->CellConnectivity,
249                                       this->CellOffsets,
250                                       this->ShapeId,
251                                       this->NumIndices,
252                                       this->NumFaces,
253                                       token);
254         Handle = make_MeshConnHandle(conn);
255       }
256       return Handle.PrepareForExecution(CUDA(), token);
257 #endif
258 #ifdef VTKM_ENABLE_KOKKOS
259     case VTKM_DEVICE_ADAPTER_KOKKOS:
260       using KOKKOS = vtkm::cont::DeviceAdapterTagKokkos;
261       {
262         MeshConnSingleType<KOKKOS> conn(this->FaceConnectivity,
263                                         this->CellConnectivity,
264                                         this->CellOffsets,
265                                         this->ShapeId,
266                                         this->NumIndices,
267                                         this->NumFaces,
268                                         token);
269         Handle = make_MeshConnHandle(conn);
270       }
271       return Handle.PrepareForExecution(KOKKOS(), token);
272 #endif
273     case VTKM_DEVICE_ADAPTER_SERIAL:
274       VTKM_FALLTHROUGH;
275     default:
276       using SERIAL = vtkm::cont::DeviceAdapterTagSerial;
277       {
278         MeshConnSingleType<SERIAL> conn(this->FaceConnectivity,
279                                         this->CellConnectivity,
280                                         this->CellOffsets,
281                                         this->ShapeId,
282                                         this->NumIndices,
283                                         this->NumFaces,
284                                         token);
285         Handle = make_MeshConnHandle(conn);
286       }
287       return Handle.PrepareForExecution(SERIAL(), token);
288   }
289 }
290 
StructuredContainer(const vtkm::cont::CellSetStructured<3> & cellset,const vtkm::cont::CoordinateSystem & coords,Id4Handle & triangles)291 StructuredContainer::StructuredContainer(const vtkm::cont::CellSetStructured<3>& cellset,
292                                          const vtkm::cont::CoordinateSystem& coords,
293                                          Id4Handle& triangles)
294   : Coords(coords)
295   , Cellset(cellset)
296 {
297 
298   Triangles = triangles;
299   Intersector.SetUseWaterTight(true);
300 
301   PointDims = Cellset.GetPointDimensions();
302   CellDims = Cellset.GetCellDimensions();
303 
304   this->Intersector.SetData(Coords, Triangles);
305 }
306 
Construct(const vtkm::cont::DeviceAdapterId deviceId,vtkm::cont::Token & token)307 const MeshConnectivityBase* StructuredContainer::Construct(
308   const vtkm::cont::DeviceAdapterId deviceId,
309   vtkm::cont::Token& token)
310 {
311 
312   MeshConnStructured conn(CellDims, PointDims);
313   Handle = make_MeshConnHandle(conn);
314 
315   switch (deviceId.GetValue())
316   {
317 #ifdef VTKM_ENABLE_OPENMP
318     case VTKM_DEVICE_ADAPTER_OPENMP:
319       return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagOpenMP(), token);
320 #endif
321 #ifdef VTKM_ENABLE_TBB
322     case VTKM_DEVICE_ADAPTER_TBB:
323       return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagTBB(), token);
324 #endif
325 #ifdef VTKM_ENABLE_CUDA
326     case VTKM_DEVICE_ADAPTER_CUDA:
327       return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagCuda(), token);
328 #endif
329 #ifdef VTKM_ENABLE_KOKKOS
330     case VTKM_DEVICE_ADAPTER_KOKKOS:
331       return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagKokkos(), token);
332 #endif
333     case VTKM_DEVICE_ADAPTER_SERIAL:
334       VTKM_FALLTHROUGH;
335     default:
336       return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagSerial(), token);
337   }
338 }
339 }
340 }
341 } //namespace vtkm::rendering::raytracing
342