| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2013-08-18 14:16:15 +00:00
										 |  |  |  * Copyright 2011-2013 Blender Foundation | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-08-18 14:16:15 +00:00
										 |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-08-18 14:16:15 +00:00
										 |  |  |  * http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-08-18 14:16:15 +00:00
										 |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							| 
									
										
										
										
											2014-12-25 02:50:24 +01:00
										 |  |  |  * limitations under the License. | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-27 00:10:48 +06:00
										 |  |  | /* TODO(sergey): Consider moving portable ctz/clz stuff to util. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | CCL_NAMESPACE_BEGIN | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* "Correlated Multi-Jittered Sampling"
 | 
					
						
							|  |  |  |  * Andrew Kensler, Pixar Technical Memo 13-01, 2013 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* todo: find good value, suggested 64 gives pattern on cornell box ceiling */ | 
					
						
							|  |  |  | #define CMJ_RANDOM_OFFSET_LIMIT 4096
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline bool cmj_is_pow2(int i) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-24 14:23:45 +01:00
										 |  |  |   return (i > 1) && ((i & (i - 1)) == 0); | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline int cmj_fast_mod_pow2(int a, int b) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return (a & (b - 1)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:44:33 +05:00
										 |  |  | /* b must be > 1 */ | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline int cmj_fast_div_pow2(int a, int b) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-26 14:20:21 +06:00
										 |  |  |   kernel_assert(b > 1); | 
					
						
							| 
									
										
										
										
											2019-08-26 15:08:46 +02:00
										 |  |  |   return a >> count_trailing_zeros(b); | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline uint cmj_w_mask(uint w) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-26 14:20:21 +06:00
										 |  |  |   kernel_assert(w > 1); | 
					
						
							| 
									
										
										
										
											2019-08-26 15:08:46 +02:00
										 |  |  |   return ((1 << (32 - count_leading_zeros(w))) - 1); | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline uint cmj_permute(uint i, uint l, uint p) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   uint w = l - 1; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |   if ((l & w) == 0) { | 
					
						
							|  |  |  |     /* l is a power of two (fast) */ | 
					
						
							|  |  |  |     i ^= p; | 
					
						
							|  |  |  |     i *= 0xe170893d; | 
					
						
							|  |  |  |     i ^= p >> 16; | 
					
						
							|  |  |  |     i ^= (i & w) >> 4; | 
					
						
							|  |  |  |     i ^= p >> 8; | 
					
						
							|  |  |  |     i *= 0x0929eb3f; | 
					
						
							|  |  |  |     i ^= p >> 23; | 
					
						
							|  |  |  |     i ^= (i & w) >> 1; | 
					
						
							|  |  |  |     i *= 1 | p >> 27; | 
					
						
							|  |  |  |     i *= 0x6935fa69; | 
					
						
							|  |  |  |     i ^= (i & w) >> 11; | 
					
						
							|  |  |  |     i *= 0x74dcb303; | 
					
						
							|  |  |  |     i ^= (i & w) >> 2; | 
					
						
							|  |  |  |     i *= 0x9e501cc3; | 
					
						
							|  |  |  |     i ^= (i & w) >> 2; | 
					
						
							|  |  |  |     i *= 0xc860a3df; | 
					
						
							|  |  |  |     i &= w; | 
					
						
							|  |  |  |     i ^= i >> 5; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |     return (i + p) & w; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* l is not a power of two (slow) */ | 
					
						
							|  |  |  |     w = cmj_w_mask(w); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |     do { | 
					
						
							|  |  |  |       i ^= p; | 
					
						
							|  |  |  |       i *= 0xe170893d; | 
					
						
							|  |  |  |       i ^= p >> 16; | 
					
						
							|  |  |  |       i ^= (i & w) >> 4; | 
					
						
							|  |  |  |       i ^= p >> 8; | 
					
						
							|  |  |  |       i *= 0x0929eb3f; | 
					
						
							|  |  |  |       i ^= p >> 23; | 
					
						
							|  |  |  |       i ^= (i & w) >> 1; | 
					
						
							|  |  |  |       i *= 1 | p >> 27; | 
					
						
							|  |  |  |       i *= 0x6935fa69; | 
					
						
							|  |  |  |       i ^= (i & w) >> 11; | 
					
						
							|  |  |  |       i *= 0x74dcb303; | 
					
						
							|  |  |  |       i ^= (i & w) >> 2; | 
					
						
							|  |  |  |       i *= 0x9e501cc3; | 
					
						
							|  |  |  |       i ^= (i & w) >> 2; | 
					
						
							|  |  |  |       i *= 0xc860a3df; | 
					
						
							|  |  |  |       i &= w; | 
					
						
							|  |  |  |       i ^= i >> 5; | 
					
						
							| 
									
										
										
										
											2015-03-28 00:15:15 +05:00
										 |  |  |     } while (i >= l); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |     return (i + p) % l; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline uint cmj_hash(uint i, uint p) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   i ^= p; | 
					
						
							|  |  |  |   i ^= i >> 17; | 
					
						
							|  |  |  |   i ^= i >> 10; | 
					
						
							|  |  |  |   i *= 0xb36534e5; | 
					
						
							|  |  |  |   i ^= i >> 12; | 
					
						
							|  |  |  |   i ^= i >> 21; | 
					
						
							|  |  |  |   i *= 0x93fc4795; | 
					
						
							|  |  |  |   i ^= 0xdf6e307f; | 
					
						
							|  |  |  |   i ^= i >> 17; | 
					
						
							|  |  |  |   i *= 1 | p >> 18; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |   return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-26 17:30:02 +01:00
										 |  |  | ccl_device_inline uint cmj_hash_simple(uint i, uint p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   i = (i ^ 61) ^ p; | 
					
						
							|  |  |  |   i += i << 3; | 
					
						
							|  |  |  |   i ^= i >> 4; | 
					
						
							|  |  |  |   i *= 0x27d4eb2d; | 
					
						
							|  |  |  |   return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device_inline float cmj_randfloat(uint i, uint p) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return cmj_hash(i, p) * (1.0f / 4294967808.0f); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __CMJ__
 | 
					
						
							| 
									
										
										
										
											2013-11-16 00:17:10 +01:00
										 |  |  | ccl_device float cmj_sample_1D(int s, int N, int p) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-23 23:04:50 +00:00
										 |  |  |   kernel_assert(s < N); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |   uint x = cmj_permute(s, N, p * 0x68bc21eb); | 
					
						
							|  |  |  |   float jx = cmj_randfloat(s, p * 0x967a889b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float invN = 1.0f / N; | 
					
						
							|  |  |  |   return (x + jx) * invN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:12:06 +02:00
										 |  |  | /* TODO(sergey): Do some extra tests and consider moving to util_math.h. */ | 
					
						
							|  |  |  | ccl_device_inline int cmj_isqrt(int value) | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-03-13 12:14:43 +05:00
										 |  |  | #  if defined(__KERNEL_CUDA__)
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:12:06 +02:00
										 |  |  |   return float_to_int(__fsqrt_ru(value)); | 
					
						
							|  |  |  | #  elif defined(__KERNEL_GPU__)
 | 
					
						
							|  |  |  |   return float_to_int(sqrtf(value)); | 
					
						
							| 
									
										
										
										
											2015-03-13 12:14:43 +05:00
										 |  |  | #  else
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:12:06 +02:00
										 |  |  |   /* This is a work around for fast-math on CPU which might replace sqrtf()
 | 
					
						
							|  |  |  |    * with am approximated version. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   return float_to_int(sqrtf(value) + 1e-6f); | 
					
						
							| 
									
										
										
										
											2015-03-13 12:14:43 +05:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:12:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   kernel_assert(s < N); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int m = cmj_isqrt(N); | 
					
						
							| 
									
										
										
										
											2016-04-28 23:46:00 +02:00
										 |  |  |   int n = (N - 1) / m + 1; | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |   float invN = 1.0f / N; | 
					
						
							|  |  |  |   float invm = 1.0f / m; | 
					
						
							|  |  |  |   float invn = 1.0f / n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s = cmj_permute(s, N, p * 0x51633e2d); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int sdivm, smodm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (cmj_is_pow2(m)) { | 
					
						
							|  |  |  |     sdivm = cmj_fast_div_pow2(s, m); | 
					
						
							|  |  |  |     smodm = cmj_fast_mod_pow2(s, m); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2014-08-28 15:15:59 +06:00
										 |  |  |     /* Doing s*inmv gives precision issues here. */ | 
					
						
							|  |  |  |     sdivm = s / m; | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  |     smodm = s - sdivm * m; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint sx = cmj_permute(smodm, m, p * 0x68bc21eb); | 
					
						
							|  |  |  |   uint sy = cmj_permute(sdivm, n, p * 0x02e5be93); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float jx = cmj_randfloat(s, p * 0x967a889b); | 
					
						
							|  |  |  |   float jy = cmj_randfloat(s, p * 0x368cc8b7); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-11 21:58:48 +00:00
										 |  |  |   *fx = (sx + (sy + jx) * invn) * invm; | 
					
						
							|  |  |  |   *fy = (s + jy) * invN; | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 15:12:44 +01:00
										 |  |  | ccl_device float pmj_sample_1D(KernelGlobals *kg, int sample, int rng_hash, int dimension) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Fallback to random */ | 
					
						
							| 
									
										
										
										
											2020-03-08 21:31:47 +01:00
										 |  |  |   if (sample >= NUM_PMJ_SAMPLES) { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:27:25 +02:00
										 |  |  |     const int p = rng_hash + dimension; | 
					
						
							| 
									
										
										
										
											2020-03-02 15:12:44 +01:00
										 |  |  |     return cmj_randfloat(sample, p); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-04-22 16:27:25 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     const uint mask = cmj_hash_simple(dimension, rng_hash) & 0x007fffff; | 
					
						
							|  |  |  |     const int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2; | 
					
						
							|  |  |  |     return __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ mask) - 1.0f; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-03-02 15:12:44 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:27:25 +02:00
										 |  |  | ccl_device float2 pmj_sample_2D(KernelGlobals *kg, int sample, int rng_hash, int dimension) | 
					
						
							| 
									
										
										
										
											2020-03-02 15:12:44 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-08 21:31:47 +01:00
										 |  |  |   if (sample >= NUM_PMJ_SAMPLES) { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:27:25 +02:00
										 |  |  |     const int p = rng_hash + dimension; | 
					
						
							|  |  |  |     const float fx = cmj_randfloat(sample, p); | 
					
						
							|  |  |  |     const float fy = cmj_randfloat(sample, p + 1); | 
					
						
							|  |  |  |     return make_float2(fx, fy); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     const int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2; | 
					
						
							|  |  |  |     const uint maskx = cmj_hash_simple(dimension, rng_hash) & 0x007fffff; | 
					
						
							|  |  |  |     const uint masky = cmj_hash_simple(dimension + 1, rng_hash) & 0x007fffff; | 
					
						
							|  |  |  |     const float fx = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ maskx) - 1.0f; | 
					
						
							|  |  |  |     const float fy = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index + 1) ^ masky) - | 
					
						
							|  |  |  |                      1.0f; | 
					
						
							|  |  |  |     return make_float2(fx, fy); | 
					
						
							| 
									
										
										
										
											2020-03-02 15:12:44 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 16:06:22 +00:00
										 |  |  | CCL_NAMESPACE_END |