89a379cf3561a48fc690ff7046adf6cc722bb3d9
[blender.git] / intern / cycles / bvh / bvh_params.h
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 #ifndef __BVH_PARAMS_H__
19 #define __BVH_PARAMS_H__
20
21 #include "util/util_boundbox.h"
22
23 #include "kernel/kernel_types.h"
24
25 CCL_NAMESPACE_BEGIN
26
27 /* Layout of BVH tree.
28  *
29  * For example, how wide BVH tree is, in terms of number of children
30  * per node.
31  */
32 typedef KernelBVHLayout BVHLayout;
33
34 /* Names bitflag type to denote which BVH layouts are supported by
35  * particular area.
36  *
37  * Bitflags are the BVH_LAYOUT_* values.
38  */
39 typedef int BVHLayoutMask;
40
41 /* Get human readable name of BVH layout. */
42 const char *bvh_layout_name(BVHLayout layout);
43
44 /* BVH Parameters */
45
46 class BVHParams
47 {
48 public:
49
50         /* spatial split area threshold */
51         bool use_spatial_split;
52         float spatial_split_alpha;
53
54         /* Unaligned nodes creation threshold */
55         float unaligned_split_threshold;
56
57         /* SAH costs */
58         float sah_node_cost;
59         float sah_primitive_cost;
60
61         /* number of primitives in leaf */
62         int min_leaf_size;
63         int max_triangle_leaf_size;
64         int max_motion_triangle_leaf_size;
65         int max_curve_leaf_size;
66         int max_motion_curve_leaf_size;
67
68         /* object or mesh level bvh */
69         bool top_level;
70
71         /* BVH layout to be built. */
72         BVHLayout bvh_layout;
73
74         /* Mask of primitives to be included into the BVH. */
75         int primitive_mask;
76
77         /* Use unaligned bounding boxes.
78          * Only used for curves BVH.
79          */
80         bool use_unaligned_nodes;
81
82         /* Split time range to this number of steps and create leaf node for each
83          * of this time steps.
84          *
85          * Speeds up rendering of motion curve primitives in the cost of higher
86          * memory usage.
87          */
88         int num_motion_curve_steps;
89
90         /* Same as above, but for triangle primitives. */
91         int num_motion_triangle_steps;
92
93         /* fixed parameters */
94         enum {
95                 MAX_DEPTH = 64,
96                 MAX_SPATIAL_DEPTH = 48,
97                 NUM_SPATIAL_BINS = 32
98         };
99
100         BVHParams()
101         {
102                 use_spatial_split = true;
103                 spatial_split_alpha = 1e-5f;
104
105                 unaligned_split_threshold = 0.7f;
106
107                 /* todo: see if splitting up primitive cost to be separate for triangles
108                  * and curves can help. so far in tests it doesn't help, but why? */
109                 sah_node_cost = 1.0f;
110                 sah_primitive_cost = 1.0f;
111
112                 min_leaf_size = 1;
113                 max_triangle_leaf_size = 8;
114                 max_motion_triangle_leaf_size = 8;
115                 max_curve_leaf_size = 1;
116                 max_motion_curve_leaf_size = 4;
117
118                 top_level = false;
119                 bvh_layout = BVH_LAYOUT_BVH2;
120                 use_unaligned_nodes = false;
121
122                 primitive_mask = PRIMITIVE_ALL;
123
124                 num_motion_curve_steps = 0;
125                 num_motion_triangle_steps = 0;
126         }
127
128         /* SAH costs */
129         __forceinline float cost(int num_nodes, int num_primitives) const
130         { return node_cost(num_nodes) + primitive_cost(num_primitives); }
131
132         __forceinline float primitive_cost(int n) const
133         { return n*sah_primitive_cost; }
134
135         __forceinline float node_cost(int n) const
136         { return n*sah_node_cost; }
137
138         __forceinline bool small_enough_for_leaf(int size, int level)
139         { return (size <= min_leaf_size || level >= MAX_DEPTH); }
140
141         /* Gets best matching BVH.
142          *
143          * If the requested layout is supported by the device, it will be used.
144          * Otherwise, widest supported layout below that will be used.
145          */
146         static BVHLayout best_bvh_layout(BVHLayout requested_layout,
147                                          BVHLayoutMask supported_layouts);
148 };
149
150 /* BVH Reference
151  *
152  * Reference to a primitive. Primitive index and object are sneakily packed
153  * into BoundBox to reduce memory usage and align nicely */
154
155 class BVHReference
156 {
157 public:
158         __forceinline BVHReference() {}
159
160         __forceinline BVHReference(const BoundBox& bounds_,
161                                    int prim_index_,
162                                    int prim_object_,
163                                    int prim_type,
164                                    float time_from = 0.0f,
165                                    float time_to = 1.0f)
166                 : rbounds(bounds_),
167                   time_from_(time_from),
168                   time_to_(time_to)
169         {
170                 rbounds.min.w = __int_as_float(prim_index_);
171                 rbounds.max.w = __int_as_float(prim_object_);
172                 type = prim_type;
173         }
174
175         __forceinline const BoundBox& bounds() const { return rbounds; }
176         __forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
177         __forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
178         __forceinline int prim_type() const { return type; }
179         __forceinline float time_from() const { return time_from_; }
180         __forceinline float time_to() const { return time_to_; }
181
182
183         BVHReference& operator=(const BVHReference &arg) {
184                 if(&arg != this) {
185                         memcpy(this, &arg, sizeof(BVHReference));
186                 }
187                 return *this;
188         }
189
190
191 protected:
192         BoundBox rbounds;
193         uint type;
194         float time_from_, time_to_;
195 };
196
197 /* BVH Range
198  *
199  * Build range used during construction, to indicate the bounds and place in
200  * the reference array of a subset of primitives Again uses trickery to pack
201  * integers into BoundBox for alignment purposes. */
202
203 class BVHRange
204 {
205 public:
206         __forceinline BVHRange()
207         {
208                 rbounds.min.w = __int_as_float(0);
209                 rbounds.max.w = __int_as_float(0);
210         }
211
212         __forceinline BVHRange(const BoundBox& bounds_, int start_, int size_)
213         : rbounds(bounds_)
214         {
215                 rbounds.min.w = __int_as_float(start_);
216                 rbounds.max.w = __int_as_float(size_);
217         }
218
219         __forceinline BVHRange(const BoundBox& bounds_, const BoundBox& cbounds_, int start_, int size_)
220         : rbounds(bounds_), cbounds(cbounds_)
221         {
222                 rbounds.min.w = __int_as_float(start_);
223                 rbounds.max.w = __int_as_float(size_);
224         }
225
226         __forceinline void set_start(int start_) { rbounds.min.w = __int_as_float(start_); }
227
228         __forceinline const BoundBox& bounds() const { return rbounds; }
229         __forceinline const BoundBox& cent_bounds() const { return cbounds; }
230         __forceinline int start() const { return __float_as_int(rbounds.min.w); }
231         __forceinline int size() const { return __float_as_int(rbounds.max.w); }
232         __forceinline int end() const { return start() + size(); }
233
234 protected:
235         BoundBox rbounds;
236         BoundBox cbounds;
237 };
238
239 /* BVH Spatial Bin */
240
241 struct BVHSpatialBin
242 {
243         BoundBox bounds;
244         int enter;
245         int exit;
246
247         __forceinline BVHSpatialBin()
248         {
249         }
250 };
251
252 /* BVH Spatial Storage
253  *
254  * The idea of this storage is have thread-specific storage for the spatial
255  * splitters. We can pre-allocate this storage in advance and avoid heavy memory
256  * operations during split process.
257  */
258
259 struct BVHSpatialStorage {
260         /* Accumulated bounds when sweeping from right to left.  */
261         vector<BoundBox> right_bounds;
262
263         /* Bins used for histogram when selecting best split plane. */
264         BVHSpatialBin bins[3][BVHParams::NUM_SPATIAL_BINS];
265
266         /* Temporary storage for the new references. Used by spatial split to store
267          * new references in before they're getting inserted into actual array,
268          */
269         vector<BVHReference> new_references;
270 };
271
272 CCL_NAMESPACE_END
273
274 #endif /* __BVH_PARAMS_H__ */