@@ -105,8 +105,8 @@ mutable struct SPPMPixelListNode
105
105
end
106
106
end
107
107
108
- struct SPPMIntegrator <: Integrator
109
- camera:: C where C <: Camera
108
+ struct SPPMIntegrator{C <: Camera } <: Integrator
109
+ camera:: C
110
110
initial_search_radius:: Float32
111
111
max_depth:: Int64
112
112
n_iterations:: Int64
@@ -122,7 +122,7 @@ struct SPPMIntegrator <: Integrator
122
122
photons_per_iteration > 0
123
123
? photons_per_iteration : area (get_film (camera). crop_bounds)
124
124
)
125
- new (
125
+ new {C} (
126
126
camera, initial_search_radius, max_depth,
127
127
n_iterations, photons_per_iteration, write_frequency,
128
128
)
@@ -149,16 +149,17 @@ function (i::SPPMIntegrator)(scene::Scene)
149
149
n_tiles:: Point2 = Int64 .(floor .((pixel_extent .+ tile_size) ./ tile_size))
150
150
151
151
sampler = UniformSampler (1 )
152
+ mempools = [MemoryPool (round (Int, 100_000 )) for _ in 1 : Threads. maxthreadid ()]
152
153
for iteration in 1 : i. n_iterations
153
154
_generate_visible_sppm_points! (
154
- i, pixels, scene,
155
+ mempools, i, pixels, scene,
155
156
n_tiles, tile_size, sampler,
156
157
pixel_bounds, inv_sqrt_spp,
157
158
)
158
159
_clean_grid! (grid)
159
160
grid_bounds, grid_resolution = _populate_grid! (grid, pixels)
160
161
_trace_photons! (
161
- i, scene, iteration, light_distribution,
162
+ mempools, i, scene, iteration, light_distribution,
162
163
grid, grid_bounds, grid_resolution,
163
164
n_pixels,
164
165
)
@@ -173,14 +174,16 @@ function (i::SPPMIntegrator)(scene::Scene)
173
174
end
174
175
175
176
function _generate_visible_sppm_points! (
176
- i:: SPPMIntegrator , pixels:: Matrix{SPPMPixel} , scene:: Scene ,
177
- n_tiles:: Point2 , tile_size:: Int64 , sampler:: S ,
178
- pixel_bounds:: Bounds2 , inv_sqrt_spp:: Float32 ,
179
- ) where S<: AbstractSampler
177
+ mempools, i:: SPPMIntegrator , pixels:: Matrix{SPPMPixel} , scene:: Scene ,
178
+ n_tiles:: Point2 , tile_size:: Int64 , sampler:: S ,
179
+ pixel_bounds:: Bounds2 , inv_sqrt_spp:: Float32 ,
180
+ ) where S<: AbstractSampler
181
+
180
182
width, height = n_tiles
181
183
total_tiles = width * height - 1
182
184
183
185
bar = get_progress_bar (total_tiles, " Camera pass: " )
186
+
184
187
Threads. @threads for k in 0 : total_tiles
185
188
x, y = k % width, k ÷ width
186
189
tile = Point2f (x, y)
@@ -189,45 +192,47 @@ function _generate_visible_sppm_points!(
189
192
tb_min = pixel_bounds. p_min .+ tile .* tile_size
190
193
tb_max = min .(tb_min .+ (tile_size - 1 ), pixel_bounds. p_max)
191
194
tile_bounds = Bounds2 (tb_min, tb_max)
195
+ pool = mempools[Threads. threadid ()]
192
196
for pixel_point in tile_bounds
197
+ free_all (pool)
193
198
start_pixel! (tile_sampler, pixel_point)
194
199
# set_sample_number!(tile_sampler, iteration)
195
200
196
201
camera_sample = get_camera_sample (tile_sampler, pixel_point)
197
- ray , β = generate_ray_differential (i. camera, camera_sample)
202
+ rayd :: RayDifferentials , β = generate_ray_differential (pool, i. camera, camera_sample)
198
203
β ≈ 0f0 && continue
199
204
β = RGBSpectrum (β)
200
205
@real_assert ! isnan (β)
201
- scale_differentials! (ray , inv_sqrt_spp)
206
+ scale_differentials! (rayd , inv_sqrt_spp)
202
207
# Follow camera ray path until a visible point is created.
203
208
# Get SPPMPixel for current `pixel`.
204
209
pixel_point = Int64 .(pixel_point)
205
210
pixel = pixels[pixel_point[2 ], pixel_point[1 ]]
206
211
specular_bounce = false
207
212
depth = 1
208
213
while depth ≤ i. max_depth
209
- hit, surface_interaction = intersect! (scene, ray )
214
+ hit, primitive, surface_interaction = intersect! (pool, scene, rayd )
210
215
if ! hit # Accumulate light contributions to the background.
211
216
for light in scene. lights
212
- pixel. Ld += β * le (light, ray )
217
+ pixel. Ld += β * le (light, rayd )
213
218
end
214
219
break
215
220
end
216
221
# Process SPPM camera ray intersection.
217
222
# Compute BSDF at SPPM camera ray intersection.
218
- bsdf = compute_scattering! (pool, surface_interaction, ray , true )
223
+ bsdf = compute_scattering! (pool, primitive, surface_interaction, rayd , true )
219
224
if bsdf ≡ nothing
220
- ray = spawn_ray (surface_interaction, ray . d )
225
+ rayd = allocate (pool, RayDifferentials, spawn_ray (pool, surface_interaction, rayd . d) )
221
226
continue
222
227
end
223
228
# Accumulate direct illumination at
224
229
# SPPM camera-ray intersection.
225
- wo = - ray . d
230
+ wo = - rayd . d
226
231
if depth == 1 || specular_bounce
227
232
pixel. Ld += β * le (surface_interaction, wo)
228
233
end
229
234
pixel. Ld += uniform_sample_one_light (
230
- surface_interaction, scene, tile_sampler,
235
+ pool, bsdf, surface_interaction, scene, tile_sampler,
231
236
)
232
237
# Possibly create visible point and end camera path.
233
238
is_diffuse = num_components (bsdf,
@@ -261,7 +266,7 @@ function _generate_visible_sppm_points!(
261
266
β /= continue_probability
262
267
@real_assert ! isnan (β) && ! isinf (β)
263
268
end
264
- ray = RayDifferentials ( spawn_ray (surface_interaction, wi))
269
+ rayd = allocate (pool, RayDifferentials, spawn_ray (pool, surface_interaction, wi))
265
270
depth += 1
266
271
end
267
272
end
@@ -318,7 +323,7 @@ function _populate_grid!(
318
323
end
319
324
320
325
function _trace_photons! (
321
- i:: SPPMIntegrator , scene:: Scene , iteration:: Int64 ,
326
+ mempools, i:: SPPMIntegrator , scene:: Scene , iteration:: Int64 ,
322
327
light_distribution:: Distribution1D ,
323
328
grid:: Vector{Maybe{SPPMPixelListNode}} ,
324
329
grid_bounds:: Bounds3 , grid_resolution:: Point3 ,
@@ -332,6 +337,7 @@ function _trace_photons!(
332
337
shutter_open = i. camera. core. core. shutter_open
333
338
shutter_close = i. camera. core. core. shutter_close
334
339
Threads. @threads for photon_index in 0 : i. photons_per_iteration- 1
340
+ pool = mempools[Threads. threadid ()]
335
341
# Follow photon path for `photon_index`.
336
342
halton_index = halton_base + photon_index
337
343
halton_dim = 0
@@ -359,10 +365,10 @@ function _trace_photons!(
359
365
halton_dim += 5
360
366
# Generate `photon_ray` from light source and initialize β.
361
367
le, ray, light_normal, pdf_pos, pdf_dir = sample_le (
362
- light, u_light_0, u_light_1, u_light_time,
368
+ pool, light, u_light_0, u_light_1, u_light_time,
363
369
)
364
370
(pdf_pos ≈ 0f0 || pdf_dir ≈ 0f0 || is_black (le)) && continue
365
- photon_ray = RayDifferentials ( ray)
371
+ photon_ray = allocate (pool, RayDifferentials, ray)
366
372
β = abs (light_normal ⋅ photon_ray. d) * le / (
367
373
light_pdf * pdf_pos * pdf_dir
368
374
)
@@ -372,7 +378,7 @@ function _trace_photons!(
372
378
# Follow photon path through scene and record intersections.
373
379
depth = 1
374
380
while depth ≤ i. max_depth
375
- hit, interaction = intersect! (scene, photon_ray)
381
+ hit, primitive, interaction = intersect! (pool, scene, photon_ray)
376
382
! hit && break
377
383
if depth > 1
378
384
# Add photon contribution to nearby visible points.
@@ -385,8 +391,8 @@ function _trace_photons!(
385
391
node:: Maybe{SPPMPixelListNode} = grid[h]
386
392
while node ≢ nothing
387
393
if distance_squared (
388
- node. pixel. vp. p, interaction. core. p,
389
- ) > (node. pixel. radius^ 2 )
394
+ node. pixel. vp. p, interaction. core. p,
395
+ ) > (node. pixel. radius^ 2 )
390
396
node = node. next
391
397
continue
392
398
end
@@ -403,9 +409,10 @@ function _trace_photons!(
403
409
end
404
410
# Sample new photon direction.
405
411
# Compute BSDF at photon intersection point.
406
- compute_scattering! (pool, interaction, photon_ray, true , Importance)
407
- if interaction. bsdf ≡ nothing
408
- photon_ray = spawn_ray (interaction, photon_ray. d)
412
+ bsdf = compute_scattering! (pool, primitive, interaction, photon_ray, true , Importance)
413
+
414
+ if bsdf ≡ nothing
415
+ photon_ray = spawn_ray (pool, interaction, photon_ray. d)
409
416
continue
410
417
end
411
418
# Sample BSDF spectrum and direction `wi` for reflected photon.
@@ -415,7 +422,7 @@ function _trace_photons!(
415
422
)
416
423
halton_dim += 2
417
424
wi, fr, pdf, sampled_type = sample_f (
418
- interaction . bsdf, - photon_ray. d, bsdf_sample, BSDF_ALL,
425
+ bsdf, - photon_ray. d, bsdf_sample, BSDF_ALL,
419
426
)
420
427
(is_black (fr) || pdf ≈ 0f0 ) && break
421
428
@@ -428,7 +435,7 @@ function _trace_photons!(
428
435
end
429
436
halton_dim += 1
430
437
# β = β_new / (1f0 - q)
431
- photon_ray = RayDifferentials ( spawn_ray (interaction, wi))
438
+ photon_ray = allocate (pool, RayDifferentials, spawn_ray (pool, interaction, wi))
432
439
depth += 1
433
440
end
434
441
next! (bar)
@@ -477,8 +484,9 @@ Calculate indices of a point `p` in grid constrained by `bounds`.
477
484
Computed indices are in [0, resolution), which is the correct input for `hash`.
478
485
"""
479
486
@inline function to_grid (
480
- p:: Point3f , bounds:: Bounds3 , grid_resolution:: Point3 ,
481
- ):: Tuple{Bool,Point3{UInt64}}
487
+ p:: Point3f , bounds:: Bounds3 , grid_resolution:: Point3 ,
488
+ ):: Tuple{Bool,Point3{UInt64}}
489
+
482
490
p_offset = offset (bounds, p)
483
491
grid_point = Point3 {Int64} (
484
492
floor (grid_resolution[1 ] * p_offset[1 ]),
501
509
end
502
510
503
511
function uniform_sample_one_light (
504
- i:: SurfaceInteraction , scene:: Scene , sampler:: S ,
505
- ):: RGBSpectrum where S<: AbstractSampler
512
+ pool, bsdf, i:: SurfaceInteraction , scene:: Scene , sampler:: S ,
513
+ ):: RGBSpectrum where S<: AbstractSampler
514
+
506
515
n_lights = length (scene. lights)
507
516
n_lights == 0 && return RGBSpectrum (0f0 )
508
517
@@ -513,21 +522,22 @@ function uniform_sample_one_light(
513
522
u_light = get_2d (sampler)
514
523
u_scatter = get_2d (sampler)
515
524
516
- estimate_direct (i, u_scatter, light, u_light, scene, sampler) / light_pdf
525
+ estimate_direct (pool, bsdf, i, u_scatter, light, u_light, scene, sampler) / light_pdf
517
526
end
518
527
519
528
function estimate_direct (
520
- interaction:: SurfaceInteraction , u_scatter:: Point2f , light:: L ,
521
- u_light:: Point2f , scene:: Scene , sampler:: S , specular:: Bool = false ,
522
- ):: RGBSpectrum where {L<: Light ,S<: AbstractSampler }
529
+ pool, bsdf, interaction:: SurfaceInteraction , u_scatter:: Point2f , light:: L ,
530
+ u_light:: Point2f , scene:: Scene , sampler:: S , specular:: Bool = false ,
531
+ ):: RGBSpectrum where {L<: Light ,S<: AbstractSampler }
532
+
523
533
bsdf_flags = specular ? BSDF_ALL : (BSDF_ALL & ~ BSDF_SPECULAR)
524
534
Ld = RGBSpectrum (0f0 )
525
535
# Sample light source with multiple importance sampling.
526
- Li, wi, light_pdf, visibility = sample_li (light, interaction. core, u_light)
536
+ Li, wi, light_pdf, visibility = sample_li (pool, light, interaction. core, u_light)
527
537
if light_pdf > 0 && ! is_black (Li)
528
538
# Evaluate BSDF for light sampling strategy.
529
539
f = (
530
- interaction . bsdf (interaction. core. wo, wi, bsdf_flags)
540
+ bsdf (interaction. core. wo, wi, bsdf_flags)
531
541
*
532
542
abs (wi ⋅ interaction. shading. n)
533
543
)
@@ -540,7 +550,7 @@ function estimate_direct(
540
550
else
541
551
@real_assert false # TODO no non delta lights right now
542
552
scattering_pdf = compute_pdf (
543
- interaction . bsdf, interaction. core. wo, wi, bsdf_flags,
553
+ bsdf, interaction. core. wo, wi, bsdf_flags,
544
554
)
545
555
weight = power_heuristic (1 , light_pdf, 1 , scattering_pdf)
546
556
Ld += f * Li * weight / light_pdf
0 commit comments