Blender  V2.93
kernel_random.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "kernel/kernel_jitter.h"
18 #include "util/util_hash.h"
19 
21 
22 /* Pseudo random numbers, uncomment this for debugging correlations. Only run
23  * this single threaded on a CPU for repeatable results. */
24 //#define __DEBUG_CORRELATION__
25 
26 /* High Dimensional Sobol.
27  *
28  * Multidimensional sobol with generator matrices. Dimension 0 and 1 are equal
29  * to classic Van der Corput and Sobol sequences. */
30 
31 #ifdef __SOBOL__
32 
33 /* Skip initial numbers that for some dimensions have clear patterns that
34  * don't cover the entire sample space. Ideally we would have a better
35  * progressive pattern that doesn't suffer from this problem, because even
36  * with this offset some dimensions are quite poor.
37  */
38 # define SOBOL_SKIP 64
39 
40 ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
41 {
42  uint result = 0;
43  uint i = index + SOBOL_SKIP;
44  for (int j = 0, x; (x = find_first_set(i)); i >>= x) {
45  j += x;
46  result ^= kernel_tex_fetch(__sample_pattern_lut, 32 * dimension + j - 1);
47  }
48  return result;
49 }
50 
51 #endif /* __SOBOL__ */
52 
54  KernelGlobals *kg, uint rng_hash, int sample, int num_samples, int dimension)
55 {
56 #ifdef __DEBUG_CORRELATION__
57  return (float)drand48();
58 #endif
59  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ) {
60  return pmj_sample_1D(kg, sample, rng_hash, dimension);
61  }
62 #ifdef __CMJ__
63 # ifdef __SOBOL__
64  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
65 # endif
66  {
67  /* Correlated multi-jitter. */
68  int p = rng_hash + dimension;
69  return cmj_sample_1D(sample, num_samples, p);
70  }
71 #endif
72 
73 #ifdef __SOBOL__
74  /* Sobol sequence value using direction vectors. */
75  uint result = sobol_dimension(kg, sample, dimension);
76  float r = (float)result * (1.0f / (float)0xFFFFFFFF);
77 
78  /* Cranly-Patterson rotation using rng seed */
79  float shift;
80 
81  /* Hash rng with dimension to solve correlation issues.
82  * See T38710, T50116.
83  */
84  uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
85  shift = tmp_rng * (1.0f / (float)0xFFFFFFFF);
86 
87  return r + shift - floorf(r + shift);
88 #endif
89 }
90 
92  uint rng_hash,
93  int sample,
94  int num_samples,
95  int dimension,
96  float *fx,
97  float *fy)
98 {
99 #ifdef __DEBUG_CORRELATION__
100  *fx = (float)drand48();
101  *fy = (float)drand48();
102  return;
103 #endif
104  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ) {
105  const float2 f = pmj_sample_2D(kg, sample, rng_hash, dimension);
106  *fx = f.x;
107  *fy = f.y;
108  return;
109  }
110 #ifdef __CMJ__
111 # ifdef __SOBOL__
112  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
113 # endif
114  {
115  /* Correlated multi-jitter. */
116  int p = rng_hash + dimension;
117  cmj_sample_2D(sample, num_samples, p, fx, fy);
118  return;
119  }
120 #endif
121 
122 #ifdef __SOBOL__
123  /* Sobol. */
124  *fx = path_rng_1D(kg, rng_hash, sample, num_samples, dimension);
125  *fy = path_rng_1D(kg, rng_hash, sample, num_samples, dimension + 1);
126 #endif
127 }
128 
129 ccl_device_inline void path_rng_init(KernelGlobals *kg,
130  int sample,
131  int num_samples,
132  uint *rng_hash,
133  int x,
134  int y,
135  float *fx,
136  float *fy)
137 {
138  /* load state */
139  *rng_hash = hash_uint2(x, y);
140  *rng_hash ^= kernel_data.integrator.seed;
141 
142 #ifdef __DEBUG_CORRELATION__
143  srand48(*rng_hash + sample);
144 #endif
145 
146  if (sample == 0) {
147  *fx = 0.5f;
148  *fy = 0.5f;
149  }
150  else {
151  path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_FILTER_U, fx, fy);
152  }
153 }
154 
155 /* Linear Congruential Generator */
156 
158 {
159  /* implicit mod 2^32 */
160  *rng = (1103515245 * (*rng) + 12345);
161  return *rng;
162 }
163 
165 {
166  /* implicit mod 2^32 */
167  *rng = (1103515245 * (*rng) + 12345);
168  return (float)*rng * (1.0f / (float)0xFFFFFFFF);
169 }
170 
172 {
173  uint rng = seed;
174  lcg_step_uint(&rng);
175  return rng;
176 }
177 
178 /* Path Tracing Utility Functions
179  *
180  * For each random number in each step of the path we must have a unique
181  * dimension to avoid using the same sequence twice.
182  *
183  * For branches in the path we must be careful not to reuse the same number
184  * in a sequence and offset accordingly.
185  */
186 
189  int dimension)
190 {
191  return path_rng_1D(
192  kg, state->rng_hash, state->sample, state->num_samples, state->rng_offset + dimension);
193 }
194 
196  KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
197 {
198  path_rng_2D(kg,
199  state->rng_hash,
200  state->sample,
201  state->num_samples,
202  state->rng_offset + dimension,
203  fx,
204  fy);
205 }
206 
209  uint hash)
210 {
211  /* Use a hash instead of dimension, this is not great but avoids adding
212  * more dimensions to each bounce which reduces quality of dimensions we
213  * are already using. */
214  return path_rng_1D(kg,
215  cmj_hash_simple(state->rng_hash, hash),
216  state->sample,
217  state->num_samples,
218  state->rng_offset);
219 }
220 
222  uint rng_hash,
224  int branch,
225  int num_branches,
226  int dimension)
227 {
228  return path_rng_1D(kg,
229  rng_hash,
230  state->sample * num_branches + branch,
231  state->num_samples * num_branches,
232  state->rng_offset + dimension);
233 }
234 
236  uint rng_hash,
238  int branch,
239  int num_branches,
240  int dimension,
241  float *fx,
242  float *fy)
243 {
244  path_rng_2D(kg,
245  rng_hash,
246  state->sample * num_branches + branch,
247  state->num_samples * num_branches,
248  state->rng_offset + dimension,
249  fx,
250  fy);
251 }
252 
253 /* Utility functions to get light termination value,
254  * since it might not be needed in many cases.
255  */
258 {
259  if (kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
261  }
262  return 0.0f;
263 }
264 
266  uint rng_hash,
268  int branch,
269  int num_branches)
270 {
271  if (kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
272  return path_branched_rng_1D(kg, rng_hash, state, branch, num_branches, PRNG_LIGHT_TERMINATE);
273  }
274  return 0.0f;
275 }
276 
278 {
279  return lcg_init(state->rng_hash + state->rng_offset + state->sample * scramble);
280 }
281 
283 {
284  return lcg_init(state->rng_hash + state->rng_offset + state->sample * scramble);
285 }
286 
288 {
289  /* Implicit mod 2^32 */
290  *rng = (1103515245 * (*rng) + 12345);
291  return (float)*rng * (1.0f / (float)0xFFFFFFFF);
292 }
293 
295 {
296  if (pattern == SAMPLING_PATTERN_PMJ) {
297  /* See Section 10.2.1, "Progressive Multi-Jittered Sample Sequences", Christensen et al.
298  * We can use this to get divide sample sequence into two classes for easier variance
299  * estimation. */
300 #if defined(__GNUC__) && !defined(__KERNEL_GPU__)
301  return __builtin_popcount(sample & 0xaaaaaaaa) & 1;
302 #elif defined(__NVCC__)
303  return __popc(sample & 0xaaaaaaaa) & 1;
304 #elif defined(__KERNEL_OPENCL__)
305  return popcount(sample & 0xaaaaaaaa) & 1;
306 #else
307  /* TODO(Stefan): pop-count intrinsic for Windows with fallback for older CPUs. */
308  int i = sample & 0xaaaaaaaa;
309  i = i - ((i >> 1) & 0x55555555);
310  i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
311  i = (((i + (i >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
312  return i & 1;
313 #endif
314  }
315  else {
316  /* TODO(Stefan): Are there reliable ways of dividing CMJ and Sobol into two classes? */
317  return sample & 0x1;
318  }
319 }
320 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:83
_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 GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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 y
static unsigned long seed
Definition: btSoftBody.h:39
#define kernel_data
#define ccl_addr_space
#define kernel_tex_fetch(tex, index)
#define ccl_device_forceinline
#define ccl_device
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define floorf(x)
ccl_device float2 pmj_sample_2D(KernelGlobals *kg, int sample, int rng_hash, int dimension)
ccl_device_inline uint cmj_hash_simple(uint i, uint p)
ccl_device float pmj_sample_1D(KernelGlobals *kg, int sample, int rng_hash, int dimension)
ccl_device uint lcg_init(uint seed)
ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state, uint scramble)
ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
ccl_device uint lcg_step_uint(uint *rng)
ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension)
ccl_device_inline uint lcg_state_init(PathState *state, uint scramble)
ccl_device float lcg_step_float(uint *rng)
ccl_device_inline bool sample_is_even(int pattern, int sample)
ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, uint rng_hash, int sample, int num_samples, int dimension, float *fx, float *fy)
Definition: kernel_random.h:91
ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
ccl_device_inline void path_rng_init(KernelGlobals *kg, int sample, int num_samples, uint *rng_hash, int x, int y, float *fx, float *fy)
ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches)
ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, const ccl_addr_space PathState *state)
CCL_NAMESPACE_BEGIN ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, uint rng_hash, int sample, int num_samples, int dimension)
Definition: kernel_random.h:53
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
ccl_device_inline float path_state_rng_1D_hash(KernelGlobals *kg, const ccl_addr_space PathState *state, uint hash)
@ PRNG_LIGHT_TERMINATE
Definition: kernel_types.h:244
@ PRNG_FILTER_U
Definition: kernel_types.h:230
@ SAMPLING_PATTERN_PMJ
Definition: kernel_types.h:257
@ SAMPLING_PATTERN_CMJ
Definition: kernel_types.h:256
static ulong state[N]
static void sample(SocketReader *reader, int x, int y, float color[4])
#define hash
Definition: noise.c:169
ccl_device_inline uint hash_uint2(uint kx, uint ky)
Definition: util_hash.h:83
ccl_device_inline uint find_first_set(uint x)
Definition: util_math.h:721