Blender V4.5
eevee_raytrace.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "GPU_debug.hh"
12
13#include "eevee_instance.hh"
14
15#include "eevee_raytrace.hh"
16
17namespace blender::eevee {
18
19/* -------------------------------------------------------------------- */
23
25{
26 const SceneEEVEE &sce_eevee = inst_.scene->eevee;
27
28 ray_tracing_options_ = sce_eevee.ray_tracing_options;
29 if ((sce_eevee.flag & SCE_EEVEE_FAST_GI_ENABLED) == 0) {
30 ray_tracing_options_.trace_max_roughness = 1.0f;
31 }
32
33 tracing_method_ = RaytraceEEVEE_Method(sce_eevee.ray_tracing_method);
34 fast_gi_ray_count_ = sce_eevee.fast_gi_ray_count;
35 fast_gi_step_count_ = sce_eevee.fast_gi_step_count;
36 fast_gi_ao_only_ = (sce_eevee.fast_gi_method == FAST_GI_AO_ONLY);
37
38 use_raytracing_ = (sce_eevee.flag & SCE_EEVEE_SSR_ENABLED) != 0;
39
40 float4 data(0.0f);
41 radiance_dummy_black_tx_.ensure_2d(
43}
44
46{
47 Texture &depth_tx = inst_.render_buffers.depth_tx;
48
49 if (!use_raytracing_) {
50 /* Do not request raytracing shaders if not needed. */
51 return;
52 }
53
54#define PASS_VARIATION(_pass_name, _index, _suffix) \
55 ((_index == 0) ? _pass_name##reflect##_suffix : \
56 (_index == 1) ? _pass_name##refract##_suffix : \
57 _pass_name##diffuse##_suffix)
58
59 /* Setup. */
60 {
61 PassSimple &pass = tile_classify_ps_;
62 pass.init();
63 pass.shader_set(inst_.shaders.static_shader_get(RAY_TILE_CLASSIFY));
64 pass.bind_image("tile_raytrace_denoise_img", &tile_raytrace_denoise_tx_);
65 pass.bind_image("tile_raytrace_tracing_img", &tile_raytrace_tracing_tx_);
66 pass.bind_image("tile_horizon_denoise_img", &tile_horizon_denoise_tx_);
67 pass.bind_image("tile_horizon_tracing_img", &tile_horizon_tracing_tx_);
68 pass.bind_resources(inst_.uniform_data);
69 pass.bind_resources(inst_.gbuffer);
70 pass.dispatch(&tile_classify_dispatch_size_);
72 }
73 {
74 PassSimple &pass = tile_compact_ps_;
75 GPUShader *sh = inst_.shaders.static_shader_get(RAY_TILE_COMPACT);
76 pass.init();
77 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
78 pass.specialize_constant(sh, "resolution_scale", &data_.resolution_scale);
79 pass.shader_set(sh);
80 pass.bind_image("tile_raytrace_denoise_img", &tile_raytrace_denoise_tx_);
81 pass.bind_image("tile_raytrace_tracing_img", &tile_raytrace_tracing_tx_);
82 pass.bind_ssbo("raytrace_tracing_dispatch_buf", &raytrace_tracing_dispatch_buf_);
83 pass.bind_ssbo("raytrace_denoise_dispatch_buf", &raytrace_denoise_dispatch_buf_);
84 pass.bind_ssbo("raytrace_tracing_tiles_buf", &raytrace_tracing_tiles_buf_);
85 pass.bind_ssbo("raytrace_denoise_tiles_buf", &raytrace_denoise_tiles_buf_);
86 pass.bind_resources(inst_.uniform_data);
87 pass.dispatch(&tile_compact_dispatch_size_);
89 }
90 {
91 PassSimple &pass = generate_ps_;
92 pass.init();
93 GPUShader *sh = inst_.shaders.static_shader_get(RAY_GENERATE);
94 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
95 pass.shader_set(sh);
96 pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
97 pass.bind_image("out_ray_data_img", &ray_data_tx_);
98 pass.bind_ssbo("tiles_coord_buf", &raytrace_tracing_tiles_buf_);
99 pass.bind_resources(inst_.uniform_data);
100 pass.bind_resources(inst_.sampling);
101 pass.bind_resources(inst_.gbuffer);
102 pass.dispatch(raytrace_tracing_dispatch_buf_);
105 }
106 /* Tracing. */
107 {
108 PassSimple &pass = trace_planar_ps_;
109 pass.init();
110 GPUShader *sh = inst_.shaders.static_shader_get(RAY_TRACE_PLANAR);
111 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
112 pass.shader_set(sh);
113 pass.bind_ssbo("tiles_coord_buf", &raytrace_tracing_tiles_buf_);
114 pass.bind_image("ray_data_img", &ray_data_tx_);
115 pass.bind_image("ray_time_img", &ray_time_tx_);
116 pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
117 pass.bind_texture("depth_tx", &depth_tx);
118 pass.bind_resources(inst_.uniform_data);
119 pass.bind_resources(inst_.sampling);
120 pass.bind_resources(inst_.planar_probes);
121 pass.bind_resources(inst_.volume_probes);
122 pass.bind_resources(inst_.sphere_probes);
123 pass.bind_resources(inst_.gbuffer);
124 /* TODO(@fclem): Use another dispatch with only tiles that touches planar captures. */
125 pass.dispatch(raytrace_tracing_dispatch_buf_);
127 }
128 {
129 PassSimple &pass = trace_screen_ps_;
130 pass.init();
131 GPUShader *sh = inst_.shaders.static_shader_get(RAY_TRACE_SCREEN);
133 sh, "trace_refraction", reinterpret_cast<bool *>(&data_.trace_refraction));
134 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
135 pass.shader_set(sh);
136 pass.bind_ssbo("tiles_coord_buf", &raytrace_tracing_tiles_buf_);
137 pass.bind_image("ray_data_img", &ray_data_tx_);
138 pass.bind_image("ray_time_img", &ray_time_tx_);
139 pass.bind_texture("radiance_front_tx", &screen_radiance_front_tx_);
140 pass.bind_texture("radiance_back_tx", &screen_radiance_back_tx_);
141 pass.bind_texture("hiz_front_tx", &inst_.hiz_buffer.front.ref_tx_);
142 pass.bind_texture("hiz_back_tx", &inst_.hiz_buffer.back.ref_tx_);
143 /* Still bind front to hiz_tx for validation layers. */
144 pass.bind_resources(inst_.hiz_buffer.front);
145 pass.bind_texture("depth_tx", &depth_tx);
146 pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
147 pass.bind_resources(inst_.uniform_data);
148 pass.bind_resources(inst_.sampling);
149 pass.bind_resources(inst_.volume_probes);
150 pass.bind_resources(inst_.sphere_probes);
151 pass.bind_resources(inst_.gbuffer);
152 pass.dispatch(raytrace_tracing_dispatch_buf_);
154 }
155 {
156 PassSimple &pass = trace_fallback_ps_;
157 pass.init();
158 GPUShader *sh = inst_.shaders.static_shader_get(RAY_TRACE_FALLBACK);
159 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
160 pass.shader_set(sh);
161 pass.bind_ssbo("tiles_coord_buf", &raytrace_tracing_tiles_buf_);
162 pass.bind_image("ray_data_img", &ray_data_tx_);
163 pass.bind_image("ray_time_img", &ray_time_tx_);
164 pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
165 pass.bind_texture("depth_tx", &depth_tx);
166 pass.bind_resources(inst_.uniform_data);
167 pass.bind_resources(inst_.volume_probes);
168 pass.bind_resources(inst_.sphere_probes);
169 pass.bind_resources(inst_.sampling);
170 pass.bind_resources(inst_.gbuffer);
171 pass.dispatch(raytrace_tracing_dispatch_buf_);
173 }
174 /* Denoise. */
175 {
176 PassSimple &pass = denoise_spatial_ps_;
177 GPUShader *sh = inst_.shaders.static_shader_get(RAY_DENOISE_SPATIAL);
178 pass.init();
179 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
180 pass.specialize_constant(sh, "raytrace_resolution_scale", &data_.resolution_scale);
181 pass.specialize_constant(sh, "skip_denoise", reinterpret_cast<bool *>(&data_.skip_denoise));
182 pass.shader_set(sh);
183 pass.bind_ssbo("tiles_coord_buf", &raytrace_denoise_tiles_buf_);
184 pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
185 pass.bind_texture("depth_tx", &depth_tx);
186 pass.bind_image("ray_data_img", &ray_data_tx_);
187 pass.bind_image("ray_time_img", &ray_time_tx_);
188 pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
189 pass.bind_image("out_radiance_img", &denoised_spatial_tx_);
190 pass.bind_image("out_variance_img", &hit_variance_tx_);
191 pass.bind_image("out_hit_depth_img", &hit_depth_tx_);
192 pass.bind_image("tile_mask_img", &tile_raytrace_denoise_tx_);
193 pass.bind_resources(inst_.uniform_data);
194 pass.bind_resources(inst_.sampling);
195 pass.bind_resources(inst_.gbuffer);
196 pass.dispatch(raytrace_denoise_dispatch_buf_);
198 }
199 {
200 PassSimple &pass = denoise_temporal_ps_;
201 GPUShader *sh = inst_.shaders.static_shader_get(RAY_DENOISE_TEMPORAL);
202 pass.init();
203 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
204 pass.shader_set(sh);
205 pass.bind_resources(inst_.uniform_data);
206 pass.bind_texture("radiance_history_tx", &radiance_history_tx_);
207 pass.bind_texture("variance_history_tx", &variance_history_tx_);
208 pass.bind_texture("tilemask_history_tx", &tilemask_history_tx_);
209 pass.bind_texture("depth_tx", &depth_tx);
210 pass.bind_image("hit_depth_img", &hit_depth_tx_);
211 pass.bind_image("in_radiance_img", &denoised_spatial_tx_);
212 pass.bind_image("out_radiance_img", &denoised_temporal_tx_);
213 pass.bind_image("in_variance_img", &hit_variance_tx_);
214 pass.bind_image("out_variance_img", &denoise_variance_tx_);
215 pass.bind_ssbo("tiles_coord_buf", &raytrace_denoise_tiles_buf_);
216 pass.bind_resources(inst_.sampling);
217 pass.dispatch(raytrace_denoise_dispatch_buf_);
219 }
220 {
221 PassSimple &pass = denoise_bilateral_ps_;
222 pass.init();
223 GPUShader *sh = inst_.shaders.static_shader_get(RAY_DENOISE_BILATERAL);
224 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
225 pass.shader_set(sh);
226 pass.bind_texture("depth_tx", &depth_tx);
227 pass.bind_image("in_radiance_img", &denoised_temporal_tx_);
228 pass.bind_image("out_radiance_img", &denoised_bilateral_tx_);
229 pass.bind_image("in_variance_img", &denoise_variance_tx_);
230 pass.bind_image("tile_mask_img", &tile_raytrace_denoise_tx_);
231 pass.bind_ssbo("tiles_coord_buf", &raytrace_denoise_tiles_buf_);
232 pass.bind_resources(inst_.uniform_data);
233 pass.bind_resources(inst_.sampling);
234 pass.bind_resources(inst_.gbuffer);
235 pass.dispatch(raytrace_denoise_dispatch_buf_);
237 }
238 {
239 PassSimple &pass = horizon_schedule_ps_;
240 /* Reuse tile compaction shader but feed it with horizon scan specific buffers. */
241 GPUShader *sh = inst_.shaders.static_shader_get(RAY_TILE_COMPACT);
242 pass.init();
243 pass.specialize_constant(sh, "closure_index", 0);
244 pass.specialize_constant(sh, "resolution_scale", &data_.horizon_resolution_scale);
245 pass.shader_set(sh);
246 pass.bind_image("tile_raytrace_denoise_img", &tile_horizon_denoise_tx_);
247 pass.bind_image("tile_raytrace_tracing_img", &tile_horizon_tracing_tx_);
248 pass.bind_ssbo("raytrace_tracing_dispatch_buf", &horizon_tracing_dispatch_buf_);
249 pass.bind_ssbo("raytrace_denoise_dispatch_buf", &horizon_denoise_dispatch_buf_);
250 pass.bind_ssbo("raytrace_tracing_tiles_buf", &horizon_tracing_tiles_buf_);
251 pass.bind_ssbo("raytrace_denoise_tiles_buf", &horizon_denoise_tiles_buf_);
252 pass.bind_resources(inst_.uniform_data);
253 pass.dispatch(&horizon_schedule_dispatch_size_);
255 }
256 {
257 PassSimple &pass = horizon_setup_ps_;
258 pass.init();
259 pass.shader_set(inst_.shaders.static_shader_get(HORIZON_SETUP));
260 pass.bind_resources(inst_.uniform_data);
261 pass.bind_texture("depth_tx", &depth_tx);
262 pass.bind_texture(
263 "in_radiance_tx", &screen_radiance_front_tx_, GPUSamplerState::default_sampler());
264 pass.bind_image("out_radiance_img", &downsampled_in_radiance_tx_);
265 pass.bind_image("out_normal_img", &downsampled_in_normal_tx_);
266 pass.bind_resources(inst_.uniform_data);
267 pass.bind_resources(inst_.gbuffer);
268 pass.dispatch(&horizon_tracing_dispatch_size_);
270 }
271 {
272 PassSimple &pass = horizon_scan_ps_;
273 pass.init();
274 GPUShader *sh = inst_.shaders.static_shader_get(HORIZON_SCAN);
275 pass.specialize_constant(sh, "fast_gi_slice_count", fast_gi_ray_count_);
276 pass.specialize_constant(sh, "fast_gi_step_count", fast_gi_step_count_);
277 pass.specialize_constant(sh, "fast_gi_ao_only", fast_gi_ao_only_);
278 pass.shader_set(sh);
279 pass.bind_texture("screen_radiance_tx", &downsampled_in_radiance_tx_);
280 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
281 pass.bind_image("horizon_radiance_0_img", &horizon_radiance_tx_[0]);
282 pass.bind_image("horizon_radiance_1_img", &horizon_radiance_tx_[1]);
283 pass.bind_image("horizon_radiance_2_img", &horizon_radiance_tx_[2]);
284 pass.bind_image("horizon_radiance_3_img", &horizon_radiance_tx_[3]);
285 pass.bind_ssbo("tiles_coord_buf", &horizon_tracing_tiles_buf_);
286 pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
287 pass.bind_resources(inst_.uniform_data);
288 pass.bind_resources(inst_.hiz_buffer.front);
289 pass.bind_resources(inst_.sampling);
290 pass.bind_resources(inst_.gbuffer);
291 pass.dispatch(horizon_tracing_dispatch_buf_);
293 }
294 {
295 PassSimple &pass = horizon_denoise_ps_;
296 pass.init();
297 GPUShader *sh = inst_.shaders.static_shader_get(HORIZON_DENOISE);
298 pass.shader_set(sh);
299 pass.bind_texture("in_sh_0_tx", &horizon_radiance_tx_[0]);
300 pass.bind_texture("in_sh_1_tx", &horizon_radiance_tx_[1]);
301 pass.bind_texture("in_sh_2_tx", &horizon_radiance_tx_[2]);
302 pass.bind_texture("in_sh_3_tx", &horizon_radiance_tx_[3]);
303 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
304 pass.bind_image("out_sh_0_img", &horizon_radiance_denoised_tx_[0]);
305 pass.bind_image("out_sh_1_img", &horizon_radiance_denoised_tx_[1]);
306 pass.bind_image("out_sh_2_img", &horizon_radiance_denoised_tx_[2]);
307 pass.bind_image("out_sh_3_img", &horizon_radiance_denoised_tx_[3]);
308 pass.bind_ssbo("tiles_coord_buf", &horizon_tracing_tiles_buf_);
309 pass.bind_resources(inst_.uniform_data);
310 pass.bind_resources(inst_.sampling);
311 pass.bind_resources(inst_.hiz_buffer.front);
312 pass.dispatch(horizon_tracing_dispatch_buf_);
314 }
315 {
316 PassSimple &pass = horizon_resolve_ps_;
317 pass.init();
318 GPUShader *sh = inst_.shaders.static_shader_get(HORIZON_RESOLVE);
319 pass.shader_set(sh);
320 pass.bind_texture("depth_tx", &depth_tx);
321 pass.bind_texture("horizon_radiance_0_tx", &horizon_radiance_denoised_tx_[0]);
322 pass.bind_texture("horizon_radiance_1_tx", &horizon_radiance_denoised_tx_[1]);
323 pass.bind_texture("horizon_radiance_2_tx", &horizon_radiance_denoised_tx_[2]);
324 pass.bind_texture("horizon_radiance_3_tx", &horizon_radiance_denoised_tx_[3]);
325 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
326 pass.bind_image("closure0_img", &horizon_scan_output_tx_[0]);
327 pass.bind_image("closure1_img", &horizon_scan_output_tx_[1]);
328 pass.bind_image("closure2_img", &horizon_scan_output_tx_[2]);
329 pass.bind_ssbo("tiles_coord_buf", &horizon_denoise_tiles_buf_);
330 pass.bind_resources(inst_.uniform_data);
331 pass.bind_resources(inst_.sampling);
332 pass.bind_resources(inst_.gbuffer);
333 pass.bind_resources(inst_.volume_probes);
334 pass.bind_resources(inst_.sphere_probes);
335 pass.dispatch(horizon_denoise_dispatch_buf_);
337 }
338
339 for (int i : IndexRange(3)) {
340 const bool use_denoise = (ray_tracing_options_.flag & RAYTRACE_EEVEE_USE_DENOISE);
341 const bool use_spatial_denoise = (ray_tracing_options_.denoise_stages &
343 use_denoise;
344 const bool use_temporal_denoise = (ray_tracing_options_.denoise_stages &
346 use_spatial_denoise;
347 const bool use_bilateral_denoise = (ray_tracing_options_.denoise_stages &
349 use_temporal_denoise;
350
351 data_.closure_index = i;
352 data_.resolution_scale = max_ii(1, power_of_2_max_i(ray_tracing_options_.resolution_scale));
353 data_.skip_denoise = !use_spatial_denoise;
354 inst_.manager->warm_shader_specialization(tile_classify_ps_);
355 inst_.manager->warm_shader_specialization(tile_compact_ps_);
356 inst_.manager->warm_shader_specialization(generate_ps_);
357 if (tracing_method_ == RAYTRACE_EEVEE_METHOD_SCREEN) {
358 if (inst_.planar_probes.enabled()) {
359 inst_.manager->warm_shader_specialization(trace_planar_ps_);
360 }
361 for (int j : IndexRange(2)) {
362 data_.trace_refraction = bool(j);
363 inst_.manager->warm_shader_specialization(trace_screen_ps_);
364 }
365 }
366 else {
367 inst_.manager->warm_shader_specialization(trace_fallback_ps_);
368 }
369 if (use_spatial_denoise) {
370 inst_.manager->warm_shader_specialization(denoise_spatial_ps_);
371 }
372 if (use_temporal_denoise) {
373 inst_.manager->warm_shader_specialization(denoise_temporal_ps_);
374 }
375 if (use_bilateral_denoise) {
376 inst_.manager->warm_shader_specialization(denoise_bilateral_ps_);
377 }
378 bool use_horizon_scan = ray_tracing_options_.trace_max_roughness < 1.0f;
379 if (use_horizon_scan) {
380 inst_.manager->warm_shader_specialization(horizon_schedule_ps_);
381 inst_.manager->warm_shader_specialization(horizon_setup_ps_);
382 inst_.manager->warm_shader_specialization(horizon_scan_ps_);
383 inst_.manager->warm_shader_specialization(horizon_denoise_ps_);
384 inst_.manager->warm_shader_specialization(horizon_resolve_ps_);
385 }
386 }
387}
388
390
391void RayTraceModule::debug_draw(View & /*view*/, GPUFrameBuffer * /*view_fb*/) {}
392
394 GPUTexture *screen_radiance_back_tx,
395 eClosureBits active_closures,
396 /* TODO(fclem): Maybe wrap these two in some other class. */
397 View &main_view,
398 View &render_view)
399{
400 using namespace blender::math;
401 BLI_assert(use_raytracing_);
402
403 screen_radiance_front_tx_ = rt_buffer.radiance_feedback_tx.is_valid() ?
404 rt_buffer.radiance_feedback_tx :
405 radiance_dummy_black_tx_;
406 screen_radiance_back_tx_ = screen_radiance_back_tx ? screen_radiance_back_tx :
407 screen_radiance_front_tx_;
408
409 RaytraceEEVEE options = ray_tracing_options_;
410
411 bool use_horizon_scan = options.trace_max_roughness < 1.0f;
412
413 const int resolution_scale = max_ii(1, power_of_2_max_i(options.resolution_scale));
414 const int horizon_resolution_scale = max_ii(
415 1, power_of_2_max_i(inst_.scene->eevee.gtao_resolution));
416
417 const int2 extent = inst_.film.render_extent_get();
418 const int2 tracing_res = math::divide_ceil(extent, int2(resolution_scale));
419 const int2 tracing_res_horizon = math::divide_ceil(extent, int2(horizon_resolution_scale));
420 const int2 dummy_extent(1, 1);
421 const int2 group_size(RAYTRACE_GROUP_SIZE);
422
423 const int2 denoise_tiles = divide_ceil(extent, group_size);
424 const int2 raytrace_tiles = divide_ceil(tracing_res, group_size);
425 const int2 raytrace_tiles_horizon = divide_ceil(tracing_res_horizon, group_size);
426 const int denoise_tile_count = denoise_tiles.x * denoise_tiles.y;
427 const int raytrace_tile_count = raytrace_tiles.x * raytrace_tiles.y;
428 const int raytrace_tile_count_horizon = raytrace_tiles_horizon.x * raytrace_tiles_horizon.y;
429 tile_classify_dispatch_size_ = int3(denoise_tiles, 1);
430 horizon_schedule_dispatch_size_ = int3(divide_ceil(raytrace_tiles_horizon, group_size), 1);
431 tile_compact_dispatch_size_ = int3(divide_ceil(raytrace_tiles, group_size), 1);
432 tracing_dispatch_size_ = int3(raytrace_tiles, 1);
433 horizon_tracing_dispatch_size_ = int3(raytrace_tiles_horizon, 1);
434
435 /* TODO(fclem): Use real max closure count from shader. */
436 const int closure_count = 3;
439 tile_raytrace_denoise_tx_.ensure_2d_array(format, denoise_tiles, closure_count, usage_rw);
440 tile_raytrace_tracing_tx_.ensure_2d_array(format, raytrace_tiles, closure_count, usage_rw);
441 /* Kept as 2D array for compatibility with the tile compaction shader. */
442 tile_horizon_denoise_tx_.ensure_2d_array(format, denoise_tiles, 1, usage_rw);
443 tile_horizon_tracing_tx_.ensure_2d_array(format, raytrace_tiles_horizon, 1, usage_rw);
444
445 tile_raytrace_denoise_tx_.clear(uint4(0u));
446 tile_raytrace_tracing_tx_.clear(uint4(0u));
447 tile_horizon_denoise_tx_.clear(uint4(0u));
448 tile_horizon_tracing_tx_.clear(uint4(0u));
449
450 horizon_tracing_tiles_buf_.resize(ceil_to_multiple_u(raytrace_tile_count_horizon, 512));
451 horizon_denoise_tiles_buf_.resize(ceil_to_multiple_u(denoise_tile_count, 512));
452 raytrace_tracing_tiles_buf_.resize(ceil_to_multiple_u(raytrace_tile_count, 512));
453 raytrace_denoise_tiles_buf_.resize(ceil_to_multiple_u(denoise_tile_count, 512));
454
455 /* Data for tile classification. */
456 float roughness_mask_start = options.trace_max_roughness;
457 float roughness_mask_fade = 0.2f;
458 data_.roughness_mask_scale = 1.0 / roughness_mask_fade;
459 data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
460
461 /* Data for the radiance setup. */
462 data_.resolution_scale = resolution_scale;
463 data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
464 data_.radiance_persmat = render_view.persmat();
465 data_.full_resolution = extent;
466 data_.full_resolution_inv = 1.0f / float2(extent);
467
468 data_.horizon_resolution_scale = horizon_resolution_scale;
469 data_.horizon_resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) *
470 horizon_resolution_scale);
471 /* TODO(fclem): Eventually all uniform data is setup here. */
472
473 inst_.uniform_data.push_update();
474
476
477 GPU_debug_group_begin("Raytracing");
478
479 const bool has_active_closure = active_closures != CLOSURE_NONE;
480
481 if (has_active_closure) {
482 inst_.manager->submit(tile_classify_ps_);
483 }
484
485 data_.trace_refraction = screen_radiance_back_tx != nullptr;
486
487 for (int i = 0; i < 3; i++) {
488 result.closures[i] = trace(i, (closure_count > i), options, rt_buffer, main_view, render_view);
489 }
490
491 if (has_active_closure) {
492 if (use_horizon_scan) {
493 GPU_debug_group_begin("Horizon Scan");
494
495 downsampled_in_radiance_tx_.acquire(tracing_res_horizon, RAYTRACE_RADIANCE_FORMAT, usage_rw);
496 downsampled_in_normal_tx_.acquire(tracing_res_horizon, GPU_RGB10_A2, usage_rw);
497
498 horizon_radiance_tx_[0].acquire(tracing_res_horizon, GPU_RGBA16F, usage_rw);
499 horizon_radiance_denoised_tx_[0].acquire(tracing_res_horizon, GPU_RGBA16F, usage_rw);
500 for (int i : IndexRange(1, 3)) {
501 horizon_radiance_tx_[i].acquire(tracing_res_horizon, GPU_RGBA8, usage_rw);
502 horizon_radiance_denoised_tx_[i].acquire(tracing_res_horizon, GPU_RGBA8, usage_rw);
503 }
504 for (int i : IndexRange(3)) {
505 horizon_scan_output_tx_[i] = result.closures[i];
506 }
507
508 horizon_tracing_dispatch_buf_.clear_to_zero();
509 horizon_denoise_dispatch_buf_.clear_to_zero();
510 inst_.manager->submit(horizon_schedule_ps_);
511
512 inst_.manager->submit(horizon_setup_ps_, render_view);
513 inst_.manager->submit(horizon_scan_ps_, render_view);
514 inst_.manager->submit(horizon_denoise_ps_, render_view);
515 inst_.manager->submit(horizon_resolve_ps_, render_view);
516
517 for (int i : IndexRange(4)) {
518 horizon_radiance_tx_[i].release();
519 horizon_radiance_denoised_tx_[i].release();
520 }
521 downsampled_in_radiance_tx_.release();
522 downsampled_in_normal_tx_.release();
523
525 }
526 }
527
529
530 rt_buffer.history_persmat = render_view.persmat();
531
532 return result;
533}
534
535RayTraceResultTexture RayTraceModule::trace(
536 int closure_index,
537 bool active_layer,
539 RayTraceBuffer &rt_buffer,
540 /* TODO(fclem): Maybe wrap these two in some other class. */
541 View &main_view,
542 View &render_view)
543{
544 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[closure_index];
545
546 if (!active_layer) {
547 /* Early out. Release persistent buffers. Still acquire one dummy resource for validation. */
549 denoise_buf->radiance_history_tx.free();
550 denoise_buf->variance_history_tx.free();
551 denoise_buf->tilemask_history_tx.free();
552 return {denoise_buf->denoised_spatial_tx};
553 }
554
555 const int resolution_scale = max_ii(1, power_of_2_max_i(options.resolution_scale));
556
557 const int2 extent = inst_.film.render_extent_get();
558 const int2 tracing_res = math::divide_ceil(extent, int2(resolution_scale));
559
560 renderbuf_depth_view_ = inst_.render_buffers.depth_tx;
561
562 const bool use_denoise = (options.flag & RAYTRACE_EEVEE_USE_DENOISE);
563 const bool use_spatial_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_SPATIAL) &&
564 use_denoise;
565 const bool use_temporal_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_TEMPORAL) &&
566 use_spatial_denoise;
567 const bool use_bilateral_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_BILATERAL) &&
568 use_temporal_denoise;
569
571
572 GPU_debug_group_begin("Raytracing");
573
574 data_.thickness = options.screen_trace_thickness;
575 data_.quality = 1.0f - 0.95f * options.screen_trace_quality;
576
577 float roughness_mask_start = options.trace_max_roughness;
578 float roughness_mask_fade = 0.2f;
579 data_.roughness_mask_scale = 1.0 / roughness_mask_fade;
580 data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
581
582 data_.resolution_scale = resolution_scale;
583 data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
584 data_.history_persmat = denoise_buf->history_persmat;
585 data_.radiance_persmat = render_view.persmat();
586 data_.full_resolution = extent;
587 data_.full_resolution_inv = 1.0f / float2(extent);
588 data_.skip_denoise = !use_spatial_denoise;
589 data_.closure_index = closure_index;
591
592 /* Ray setup. */
593 raytrace_tracing_dispatch_buf_.clear_to_zero();
594 raytrace_denoise_dispatch_buf_.clear_to_zero();
595 inst_.manager->submit(tile_compact_ps_);
596
597 {
598 /* Tracing rays. */
599 ray_data_tx_.acquire(tracing_res, GPU_RGBA16F);
600 ray_time_tx_.acquire(tracing_res, RAYTRACE_RAYTIME_FORMAT);
601 ray_radiance_tx_.acquire(tracing_res, RAYTRACE_RADIANCE_FORMAT);
602
603 inst_.manager->submit(generate_ps_, render_view);
604 if (tracing_method_ == RAYTRACE_EEVEE_METHOD_SCREEN) {
605 if (inst_.planar_probes.enabled()) {
606 inst_.manager->submit(trace_planar_ps_, render_view);
607 }
608 inst_.manager->submit(trace_screen_ps_, render_view);
609 }
610 else {
611 inst_.manager->submit(trace_fallback_ps_, render_view);
612 }
613 }
614
615 RayTraceResultTexture result;
616
617 /* Spatial denoise pass is required to resolve at least one ray per pixel. */
618 {
620 hit_variance_tx_.acquire(use_temporal_denoise ? extent : int2(1), RAYTRACE_VARIANCE_FORMAT);
621 hit_depth_tx_.acquire(use_temporal_denoise ? extent : int2(1), GPU_R32F);
622 denoised_spatial_tx_ = denoise_buf->denoised_spatial_tx;
623
624 inst_.manager->submit(denoise_spatial_ps_, render_view);
625
626 result = {denoise_buf->denoised_spatial_tx};
627 }
628
629 ray_data_tx_.release();
630 ray_time_tx_.release();
631 ray_radiance_tx_.release();
632
633 if (use_temporal_denoise) {
634 denoise_buf->denoised_temporal_tx.acquire(extent, RAYTRACE_RADIANCE_FORMAT, usage_rw);
635 denoise_variance_tx_.acquire(
636 use_bilateral_denoise ? extent : int2(1), RAYTRACE_VARIANCE_FORMAT, usage_rw);
637 denoise_buf->variance_history_tx.ensure_2d(
638 RAYTRACE_VARIANCE_FORMAT, use_bilateral_denoise ? extent : int2(1), usage_rw);
640 tile_raytrace_denoise_tx_.size().xy(),
641 tile_raytrace_denoise_tx_.size().z,
642 usage_rw);
643
644 if (denoise_buf->radiance_history_tx.ensure_2d(RAYTRACE_RADIANCE_FORMAT, extent, usage_rw) ||
645 denoise_buf->valid_history == false)
646 {
647 /* If viewport resolution changes, do not try to use history. */
648 denoise_buf->tilemask_history_tx.clear(uint4(0u));
649 }
650
651 radiance_history_tx_ = denoise_buf->radiance_history_tx;
652 variance_history_tx_ = denoise_buf->variance_history_tx;
653 tilemask_history_tx_ = denoise_buf->tilemask_history_tx;
654 denoised_temporal_tx_ = denoise_buf->denoised_temporal_tx;
655
656 inst_.manager->submit(denoise_temporal_ps_, render_view);
657
658 /* Save view-projection matrix for next reprojection. */
659 denoise_buf->history_persmat = main_view.persmat();
660 /* Radiance will be swapped with history in #RayTraceResult::release().
661 * Variance is swapped with history after bilateral denoise.
662 * It keeps data-flow easier to follow. */
663 result = {denoise_buf->denoised_temporal_tx, denoise_buf->radiance_history_tx};
664 /* Not referenced by result anymore. */
665 denoise_buf->denoised_spatial_tx.release();
666
667 GPU_texture_copy(denoise_buf->tilemask_history_tx, tile_raytrace_denoise_tx_);
668 }
669
670 /* Only use history buffer for the next frame if temporal denoise was used by the current one. */
671 denoise_buf->valid_history = use_temporal_denoise;
672
673 hit_variance_tx_.release();
674 hit_depth_tx_.release();
675
676 if (use_bilateral_denoise) {
677 denoise_buf->denoised_bilateral_tx.acquire(extent, RAYTRACE_RADIANCE_FORMAT, usage_rw);
678 denoised_bilateral_tx_ = denoise_buf->denoised_bilateral_tx;
679
680 inst_.manager->submit(denoise_bilateral_ps_, render_view);
681
682 /* Swap after last use. */
684 TextureFromPool::swap(denoise_variance_tx_, denoise_buf->variance_history_tx);
685
686 result = {denoise_buf->denoised_bilateral_tx};
687 /* Not referenced by result anymore. */
688 denoise_buf->denoised_temporal_tx.release();
689 }
690
691 denoise_variance_tx_.release();
692
694
695 return result;
696}
697
699{
700 const int2 extent = inst_.film.render_extent_get();
702
704 for (int i = 0; i < 3; i++) {
705 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
706 denoise_buf->denoised_bilateral_tx.acquire(extent, RAYTRACE_RADIANCE_FORMAT, usage_rw);
707 result.closures[i] = {denoise_buf->denoised_bilateral_tx};
708 }
709 return result;
710}
711
713{
715
717 for (int i = 0; i < 3; i++) {
718 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
720 result.closures[i] = {denoise_buf->denoised_bilateral_tx};
721 }
722 return result;
723}
724
725
726} // namespace blender::eevee
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE uint ceil_to_multiple_u(uint a, uint b)
MINLINE int power_of_2_max_i(int n)
MINLINE int max_ii(int a, int b)
RaytraceEEVEE_Method
@ RAYTRACE_EEVEE_METHOD_SCREEN
@ SCE_EEVEE_FAST_GI_ENABLED
@ SCE_EEVEE_SSR_ENABLED
@ RAYTRACE_EEVEE_USE_DENOISE
@ FAST_GI_AO_ONLY
@ RAYTRACE_EEVEE_DENOISE_BILATERAL
@ RAYTRACE_EEVEE_DENOISE_SPATIAL
@ RAYTRACE_EEVEE_DENOISE_TEMPORAL
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
@ GPU_BARRIER_TEXTURE_FETCH
Definition GPU_state.hh:37
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
Definition GPU_state.hh:35
void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
eGPUTextureFormat
@ GPU_R32F
@ GPU_RGB10_A2
@ GPU_RGBA16F
@ GPU_RGBA8
BMesh const char void * data
void submit(PassSimple &pass, View &view)
static void swap(TextureFromPool &a, Texture &b)
void acquire(int2 extent, eGPUTextureFormat format, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL)
void clear(float4 values)
bool ensure_2d_array(eGPUTextureFormat format, int2 extent, int layers, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
const float4x4 persmat(int view_id=0) const
Definition draw_view.hh:161
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
Definition draw_pass.hh:440
void bind_image(const char *name, GPUTexture *image)
void specialize_constant(GPUShader *shader, const char *name, const float &data)
void dispatch(int group_len)
Definition draw_pass.hh:994
void barrier(eGPUBarrier type)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
int2 render_extent_get() const
PlanarProbeModule planar_probes
UniformDataModule uniform_data
RayTraceResult alloc_only(RayTraceBuffer &rt_buffer)
RayTraceResult render(RayTraceBuffer &rt_buffer, GPUTexture *screen_radiance_back_tx, eClosureBits active_closures, View &main_view, View &render_view)
void debug_draw(View &view, GPUFrameBuffer *view_fb)
RayTraceResult alloc_dummy(RayTraceBuffer &rt_buffer)
float2 rng_2d_get(eSamplingDimension starting_dimension) const
CCL_NAMESPACE_BEGIN struct Options options
#define RAYTRACE_VARIANCE_FORMAT
#define RBUFS_UTILITY_TEX_SLOT
#define RAYTRACE_TILEMASK_FORMAT
#define RAYTRACE_GROUP_SIZE
#define RAYTRACE_RAYTIME_FORMAT
#define RAYTRACE_RADIANCE_FORMAT
format
detail::Pass< command::DrawCommandBuf > PassSimple
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< uint32_t, 4 > uint4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
static constexpr GPUSamplerState default_sampler()
struct RaytraceEEVEE ray_tracing_options
i
Definition text_draw.cc:230