Blender  V2.93
bvh_sort.cpp
Go to the documentation of this file.
1 /*
2  * Adapted from code copyright 2009-2010 NVIDIA Corporation
3  * Modifications Copyright 2011, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "bvh/bvh_sort.h"
19 
20 #include "bvh/bvh_build.h"
21 
22 #include "util/util_algorithm.h"
23 #include "util/util_task.h"
24 
26 
27 static const int BVH_SORT_THRESHOLD = 4096;
28 
30  public:
31  int dim;
34 
37  const Transform *aligned_space)
39  {
40  }
41 
43  {
44  return (aligned_space != NULL) ?
46  prim.bounds();
47  }
48 
49  /* Compare two references.
50  *
51  * Returns value is similar to return value of strcmp().
52  */
53  __forceinline int compare(const BVHReference &ra, const BVHReference &rb) const
54  {
55  BoundBox ra_bounds = get_prim_bounds(ra), rb_bounds = get_prim_bounds(rb);
56  float ca = ra_bounds.min[dim] + ra_bounds.max[dim];
57  float cb = rb_bounds.min[dim] + rb_bounds.max[dim];
58 
59  if (ca < cb)
60  return -1;
61  else if (ca > cb)
62  return 1;
63  else if (ra.prim_object() < rb.prim_object())
64  return -1;
65  else if (ra.prim_object() > rb.prim_object())
66  return 1;
67  else if (ra.prim_index() < rb.prim_index())
68  return -1;
69  else if (ra.prim_index() > rb.prim_index())
70  return 1;
71  else if (ra.prim_type() < rb.prim_type())
72  return -1;
73  else if (ra.prim_type() > rb.prim_type())
74  return 1;
75 
76  return 0;
77  }
78 
79  bool operator()(const BVHReference &ra, const BVHReference &rb)
80  {
81  return (compare(ra, rb) < 0);
82  }
83 };
84 
87  const int job_start,
88  const int job_end,
89  const BVHReferenceCompare &compare);
90 
91 /* Multi-threaded reference sort. */
94  const int job_start,
95  const int job_end,
96  const BVHReferenceCompare &compare)
97 {
98  int start = job_start, end = job_end;
99  bool have_work = (start < end);
100  while (have_work) {
101  const int count = job_end - job_start;
102  if (count < BVH_SORT_THRESHOLD) {
103  /* Number of reference low enough, faster to finish the job
104  * in one thread rather than to spawn more threads.
105  */
106  sort(data + job_start, data + job_end + 1, compare);
107  break;
108  }
109  /* Single QSort step.
110  * Use median-of-three method for the pivot point.
111  */
112  int left = start, right = end;
113  int center = (left + right) >> 1;
114  if (compare.compare(data[left], data[center]) > 0) {
115  swap(data[left], data[center]);
116  }
117  if (compare.compare(data[left], data[right]) > 0) {
118  swap(data[left], data[right]);
119  }
120  if (compare.compare(data[center], data[right]) > 0) {
121  swap(data[center], data[right]);
122  }
123  swap(data[center], data[right - 1]);
124  BVHReference median = data[right - 1];
125  do {
126  while (compare.compare(data[left], median) < 0) {
127  ++left;
128  }
129  while (compare.compare(data[right], median) > 0) {
130  --right;
131  }
132  if (left <= right) {
133  swap(data[left], data[right]);
134  ++left;
135  --right;
136  }
137  } while (left <= right);
138  /* We only create one new task here to reduce downside effects of
139  * latency in TaskScheduler.
140  * So generally current thread keeps working on the left part of the
141  * array, and we create new task for the right side.
142  * However, if there's nothing to be done in the left side of the array
143  * we don't create any tasks and make it so current thread works on the
144  * right side.
145  */
146  have_work = false;
147  if (left < end) {
148  if (start < right) {
149  task_pool->push(
151  }
152  else {
153  start = left;
154  have_work = true;
155  }
156  }
157  if (start < right) {
158  end = right;
159  have_work = true;
160  }
161  }
162 }
163 
164 void bvh_reference_sort(int start,
165  int end,
167  int dim,
168  const BVHUnaligned *unaligned_heuristic,
169  const Transform *aligned_space)
170 {
171  const int count = end - start;
172  BVHReferenceCompare compare(dim, unaligned_heuristic, aligned_space);
173  if (count < BVH_SORT_THRESHOLD) {
174  /* It is important to not use any mutex if array is small enough,
175  * otherwise we end up in situation when we're going to sleep far
176  * too often.
177  */
178  sort(data + start, data + end, compare);
179  }
180  else {
182  bvh_reference_sort_threaded(&task_pool, data, start, end - 1, compare);
184  }
185 }
186 
void swap(T &a, T &b)
Definition: Common.h:33
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble right
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
void bvh_reference_sort(int start, int end, BVHReference *data, int dim, const BVHUnaligned *unaligned_heuristic, const Transform *aligned_space)
Definition: bvh_sort.cpp:164
static CCL_NAMESPACE_BEGIN const int BVH_SORT_THRESHOLD
Definition: bvh_sort.cpp:27
static void bvh_reference_sort_threaded(TaskPool *task_pool, BVHReference *data, const int job_start, const int job_end, const BVHReferenceCompare &compare)
Definition: bvh_sort.cpp:92
__forceinline int prim_type() const
Definition: bvh_params.h:192
__forceinline int prim_object() const
Definition: bvh_params.h:188
__forceinline const BoundBox & bounds() const
Definition: bvh_params.h:180
__forceinline int prim_index() const
Definition: bvh_params.h:184
BoundBox compute_aligned_prim_boundbox(const BVHReference &prim, const Transform &aligned_space) const
#define function_bind
TaskPool * task_pool
int count
#define CCL_NAMESPACE_END
static int left
const Transform * aligned_space
Definition: bvh_sort.cpp:33
const BVHUnaligned * unaligned_heuristic
Definition: bvh_sort.cpp:32
__forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
Definition: bvh_sort.cpp:42
__forceinline int compare(const BVHReference &ra, const BVHReference &rb) const
Definition: bvh_sort.cpp:53
bool operator()(const BVHReference &ra, const BVHReference &rb)
Definition: bvh_sort.cpp:79
BVHReferenceCompare(int dim, const BVHUnaligned *unaligned_heuristic, const Transform *aligned_space)
Definition: bvh_sort.cpp:35
float3 max
Definition: util_boundbox.h:34
float3 min
Definition: util_boundbox.h:34
void push(TaskRunFunction &&task)
Definition: util_task.cpp:36
void wait_work(Summary *stats=NULL)
Definition: util_task.cpp:42
#define __forceinline
Definition: util_defines.h:71