NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NaiveKDTreeBuilder.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2013, Radek Stibora
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the <organization> nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 #include "NaiveKDTreeBuilder.hpp"
29 #include "base/Sort.hpp"
30 #include <random>
31 
32 namespace FW
33 {
34 
36 : m_kdtree (kdtree),
37  m_platform (kdtree.getPlatform()),
38  m_params (params),
39  m_sortDim (0),
40  m_numDuplicates (0)
41 {
42 }
43 
44 
46 {
47  const Vec3i* tris = (const Vec3i*)m_kdtree.getScene()->getTriVtxIndexBuffer().getPtr();
48  const Vec3f* verts = (const Vec3f*)m_kdtree.getScene()->getVtxPosBuffer().getPtr();
49 
50  NodeSpec rootSpec;
51  rootSpec.numRef = m_kdtree.getScene()->getNumTriangles();
52  m_refStack.resize(rootSpec.numRef);
53 
54  for (int i = 0; i < rootSpec.numRef; i++)
55  {
56  m_refStack[i].triIdx = i;
57  for (int j = 0; j < 3; j++)
58  m_refStack[i].bounds.grow(verts[tris[i][j]]);
59  rootSpec.bounds.grow(m_refStack[i].bounds);
60  }
61 
62  m_progressTimer.start();
63  KDTreeNode* root = buildNode(rootSpec, 0, 0.f, 1.f);
64  m_kdtree.getTriIndices().compact();
65 
66  if (m_params.enablePrints)
67  std::printf("\rNaiveKDTreeBuilder: progress %.0f%%\n", 100.0f);
68  return root;
69 
70 }
71 
72 
73 KDTreeNode* NaiveKDTreeBuilder::buildNode(NodeSpec spec, int level, F32 progressStart, F32 progressEnd)
74 {
75  if (m_params.enablePrints && m_progressTimer.getElapsed() >= 1.0f)
76  {
77  std::printf("NaiveKDTreeBuilder: progress %.0f%%\r", progressStart * 100.0f);
78  m_progressTimer.start();
79  }
80 
81  if(spec.numRef <= m_platform.getMaxLeafSize() || level >= MaxDepth)
82  return createLeaf(spec);
83 
84  NodeSpec left, right;
85 
86  Split split = findSplit(spec, level);
87  performSplit(left, right, spec, split);
88 
89  F32 progressMid = lerp(progressStart, progressEnd, (F32)right.numRef / (F32)(left.numRef + right.numRef));
90  KDTreeNode* rightNode = buildNode(right, level + 1, progressStart, progressMid);
91  KDTreeNode* leftNode = buildNode(left, level + 1, progressMid, progressEnd);
92  return new KDTInnerNode(split.pos, split.dim, leftNode, rightNode);
93 }
94 
95 
96 KDTreeNode* NaiveKDTreeBuilder::createLeaf(const NodeSpec& spec)
97 {
98  Array<S32>& tris = m_kdtree.getTriIndices();
99  for (int i = 0; i < spec.numRef; i++)
100  tris.add(m_refStack.removeLast().triIdx);
101  return new KDTLeafNode(tris.getSize() - spec.numRef, tris.getSize());
102 }
103 
104 
105 NaiveKDTreeBuilder::Split NaiveKDTreeBuilder::findSplit (const NodeSpec& spec, S32 level)
106 {
107  Array<Reference>& refs = m_refStack;
108 
109  F32 splitPos = -1;
110  S32 dim = level % 3;
111 
112  if(m_params.builder == FW::KDTree::SpatialMedian)
113  {
114  F32 boundsMin = spec.bounds.min()[dim];
115  F32 boundsMax = spec.bounds.max()[dim];
116 
117  splitPos = (boundsMin + boundsMax) / 2;
118  }
119  else if(m_params.builder == FW::KDTree::ObjectMedian) // ??
120  {
121  m_sortDim = dim;
122  sort(this, refs.getSize() - spec.numRef, refs.getSize(), sortCompare, sortSwap);
123 
124  S32 medIdx = refs.getSize() - (int)(spec.numRef / 2);
125  splitPos = refs.get(medIdx).bounds.min()[dim];
126  }
127  else
128  FW_ASSERT(0); // Should not occur.
129 
130  Split foundSplit;
131  foundSplit.dim = dim;
132  foundSplit.pos = splitPos;
133 
134  return foundSplit;
135 }
136 
137 
138 void NaiveKDTreeBuilder::performSplit (NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const Split& split)
139 {
140  Array<Reference>& refs = m_refStack;
141  int leftStart = refs.getSize() - spec.numRef;
142  int leftEnd = leftStart;
143  int rightStart = refs.getSize();
144 
145  for (int i = leftEnd; i < rightStart; i++)
146  {
147  if (refs[i].bounds.max()[split.dim] <= split.pos)
148  {
149  swap(refs[i], refs[leftEnd++]);
150  }
151 
152  else if (refs[i].bounds.min()[split.dim] >= split.pos)
153  {
154  swap(refs[i--], refs[--rightStart]);
155  }
156  }
157 
158  // Duplicate references intersecting both sides.
159 
160  for (int i = leftEnd; i < rightStart; i++)
161  {
162  refs.add(Reference(refs.get(i)));
163  leftEnd++;
164  m_numDuplicates++;
165  }
166 
167 
168  left.numRef = leftEnd - leftStart;
169  right.numRef = refs.getSize() - rightStart;
170 
171  Vec3f leftCut = spec.bounds.max();
172  leftCut[split.dim] = split.pos;
173 
174  Vec3f rightCut = spec.bounds.min();
175  rightCut[split.dim] = split.pos;
176 
177  left.bounds = AABB(spec.bounds.min(), leftCut);
178  right.bounds = AABB(rightCut, spec.bounds.max());
179 }
180 
181 
182 bool NaiveKDTreeBuilder::sortCompare(void* data, int idxA, int idxB)
183 {
184  const NaiveKDTreeBuilder* ptr = (const NaiveKDTreeBuilder*)data;
185  int dim = ptr->m_sortDim;
186  const Reference& ra = ptr->m_refStack[idxA];
187  const Reference& rb = ptr->m_refStack[idxB];
188  F32 ca = ra.bounds.min()[dim] + ra.bounds.max()[dim];
189  F32 cb = rb.bounds.min()[dim] + rb.bounds.max()[dim];
190  return (ca < cb || (ca == cb && ra.triIdx < rb.triIdx));
191 }
192 
193 void NaiveKDTreeBuilder::sortSwap(void* data, int idxA, int idxB)
194 {
196  swap(ptr->m_refStack[idxA], ptr->m_refStack[idxB]);
197 }
198 
199 
200 }
Buffer & getTriVtxIndexBuffer(void)
Returns buffer of triangle's vertex indieces.
Definition: Scene.hpp:75
KDTreeNode * run(void)
Builds k-d tree.
void sort(void *data, int start, int end, SortCompareFunc compareFunc, SortSwapFunc swapFunc, bool multicore=false)
Definition: Sort.cpp:203
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid * data
Definition: DLLImports.inl:319
void ** ptr
Definition: DLLImports.cpp:74
Buffer & getVtxPosBuffer(void)
Returns vertex position buffer.
Definition: Scene.hpp:103
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid pixels GLint GLsizei const GLfloat value GLint GLfloat GLfloat v1 GLint GLfloat GLfloat GLfloat v2 GLint GLsizei const GLfloat value GLint GLsizei GLboolean const GLfloat value GLuint program GLuint GLfloat GLfloat GLfloat z GLuint GLint GLenum GLboolean GLsizei const GLvoid pointer GLuint GLuint const GLchar name GLenum GLsizei GLenum GLsizei GLsizei height GLenum GLuint renderbuffer GLenum GLenum GLint * params
Definition: DLLImports.inl:373
void start(void)
Definition: Timer.hpp:42
Strucure holding build parameters.
Definition: KDTree.hpp:85
K-d tree acceleration structure class.
Definition: KDTree.hpp:41
const U8 * getPtr(S64 ofs=0)
Definition: Buffer.hpp:106
NaiveKDTreeBuilder(KDTree &kdtree, const KDTree::BuildParams &params)
Constructor.
float F32
Definition: Defs.hpp:89
Scene * getScene(void) const
Gets source scene of the k-d tree.
Definition: KDTree.hpp:119
int getNumTriangles(void) const
Definition: Scene.hpp:61
#define FW_ASSERT(X)
Definition: Defs.hpp:67
signed int S32
Definition: Defs.hpp:88
T & add(void)
Definition: Array.hpp:384
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int dim
Definition: DLLImports.inl:74
Array< S32 > & getTriIndices(void)
Returns an array of triangle indices to which leaf nodes are pointig. These indices point to scene's ...
Definition: KDTree.hpp:137
BuilderType builder
Defines which builder type will be used to build the k-d tree.
Definition: KDTree.hpp:99
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction f
Definition: DLLImports.inl:88
void printf(const char *fmt,...)
Definition: Defs.cpp:225
S32 getMaxLeafSize() const
Definition: Platform.hpp:157
void compact(void)
Definition: Array.hpp:335
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level
Definition: DLLImports.inl:333
FW_CUDA_FUNC void swap(T &a, T &b)
Definition: Defs.hpp:183
bool enablePrints
Flag whether to print information during build phase.
Definition: KDTree.hpp:98
T & removeLast(void)
Definition: Array.hpp:465
F32 getElapsed(void)
Definition: Timer.hpp:44
void resize(S size)
Definition: Array.hpp:366
S getSize(void) const
Definition: Array.hpp:188
K-d tree virtual parent node class.
Definition: KDTreeNode.hpp:51
FW_CUDA_FUNC A lerp(const A &a, const A &b, const B &t)
Definition: Math.hpp:115