Blender V5.0
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(
42 gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, data);
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 gpu::Shader *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 gpu::Shader *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 gpu::Shader *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 gpu::Shader *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 gpu::Shader *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 gpu::Shader *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_);
197 /* Can either be loaded by next denoise pass as image or by combined pass as texture if this is
198 * the lass stage. */
200 }
201 {
202 PassSimple &pass = denoise_temporal_ps_;
203 gpu::Shader *sh = inst_.shaders.static_shader_get(RAY_DENOISE_TEMPORAL);
204 pass.init();
205 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
206 pass.shader_set(sh);
207 pass.bind_resources(inst_.uniform_data);
208 pass.bind_texture("radiance_history_tx", &radiance_history_tx_);
209 pass.bind_texture("variance_history_tx", &variance_history_tx_);
210 pass.bind_texture("tilemask_history_tx", &tilemask_history_tx_);
211 pass.bind_texture("depth_tx", &depth_tx);
212 pass.bind_image("hit_depth_img", &hit_depth_tx_);
213 pass.bind_image("in_radiance_img", &denoised_spatial_tx_);
214 pass.bind_image("out_radiance_img", &denoised_temporal_tx_);
215 pass.bind_image("in_variance_img", &hit_variance_tx_);
216 pass.bind_image("out_variance_img", &denoise_variance_tx_);
217 pass.bind_ssbo("tiles_coord_buf", &raytrace_denoise_tiles_buf_);
218 pass.bind_resources(inst_.sampling);
219 pass.dispatch(raytrace_denoise_dispatch_buf_);
220 /* Can either be loaded by next denoise pass as image or by combined pass as texture if this is
221 * the lass stage. */
223 }
224 {
225 PassSimple &pass = denoise_bilateral_ps_;
226 pass.init();
227 gpu::Shader *sh = inst_.shaders.static_shader_get(RAY_DENOISE_BILATERAL);
228 pass.specialize_constant(sh, "closure_index", &data_.closure_index);
229 pass.shader_set(sh);
230 pass.bind_texture("depth_tx", &depth_tx);
231 pass.bind_image("in_radiance_img", &denoised_temporal_tx_);
232 pass.bind_image("out_radiance_img", &denoised_bilateral_tx_);
233 pass.bind_image("in_variance_img", &denoise_variance_tx_);
234 pass.bind_image("tile_mask_img", &tile_raytrace_denoise_tx_);
235 pass.bind_ssbo("tiles_coord_buf", &raytrace_denoise_tiles_buf_);
236 pass.bind_resources(inst_.uniform_data);
237 pass.bind_resources(inst_.sampling);
238 pass.bind_resources(inst_.gbuffer);
239 pass.dispatch(raytrace_denoise_dispatch_buf_);
240 /* Can either be loaded and written by horizon scan as image or by combined pass as texture. */
242 }
243 {
244 PassSimple &pass = horizon_schedule_ps_;
245 /* Reuse tile compaction shader but feed it with horizon scan specific buffers. */
246 gpu::Shader *sh = inst_.shaders.static_shader_get(RAY_TILE_COMPACT);
247 pass.init();
248 pass.specialize_constant(sh, "closure_index", 0);
249 pass.specialize_constant(sh, "resolution_scale", &data_.horizon_resolution_scale);
250 pass.shader_set(sh);
251 pass.bind_image("tile_raytrace_denoise_img", &tile_horizon_denoise_tx_);
252 pass.bind_image("tile_raytrace_tracing_img", &tile_horizon_tracing_tx_);
253 pass.bind_ssbo("raytrace_tracing_dispatch_buf", &horizon_tracing_dispatch_buf_);
254 pass.bind_ssbo("raytrace_denoise_dispatch_buf", &horizon_denoise_dispatch_buf_);
255 pass.bind_ssbo("raytrace_tracing_tiles_buf", &horizon_tracing_tiles_buf_);
256 pass.bind_ssbo("raytrace_denoise_tiles_buf", &horizon_denoise_tiles_buf_);
257 pass.bind_resources(inst_.uniform_data);
258 pass.dispatch(&horizon_schedule_dispatch_size_);
260 }
261 {
262 PassSimple &pass = horizon_setup_ps_;
263 pass.init();
264 pass.shader_set(inst_.shaders.static_shader_get(HORIZON_SETUP));
265 pass.bind_resources(inst_.uniform_data);
266 pass.bind_texture("depth_tx", &depth_tx);
267 pass.bind_texture(
268 "in_radiance_tx", &screen_radiance_front_tx_, GPUSamplerState::default_sampler());
269 pass.bind_image("out_radiance_img", &downsampled_in_radiance_tx_);
270 pass.bind_image("out_normal_img", &downsampled_in_normal_tx_);
271 pass.bind_resources(inst_.uniform_data);
272 pass.bind_resources(inst_.gbuffer);
273 pass.dispatch(&horizon_tracing_dispatch_size_);
274 /* Result loaded by the next stage using samplers. */
276 }
277 {
278 PassSimple &pass = horizon_scan_ps_;
279 pass.init();
280 gpu::Shader *sh = inst_.shaders.static_shader_get(HORIZON_SCAN);
281 pass.specialize_constant(sh, "fast_gi_slice_count", fast_gi_ray_count_);
282 pass.specialize_constant(sh, "fast_gi_step_count", fast_gi_step_count_);
283 pass.specialize_constant(sh, "fast_gi_ao_only", fast_gi_ao_only_);
284 pass.shader_set(sh);
285 pass.bind_texture("screen_radiance_tx", &downsampled_in_radiance_tx_);
286 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
287 pass.bind_image("horizon_radiance_0_img", &horizon_radiance_tx_[0]);
288 pass.bind_image("horizon_radiance_1_img", &horizon_radiance_tx_[1]);
289 pass.bind_image("horizon_radiance_2_img", &horizon_radiance_tx_[2]);
290 pass.bind_image("horizon_radiance_3_img", &horizon_radiance_tx_[3]);
291 pass.bind_ssbo("tiles_coord_buf", &horizon_tracing_tiles_buf_);
292 pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
293 pass.bind_resources(inst_.uniform_data);
294 pass.bind_resources(inst_.hiz_buffer.front);
295 pass.bind_resources(inst_.sampling);
296 pass.bind_resources(inst_.gbuffer);
297 pass.dispatch(horizon_tracing_dispatch_buf_);
298 /* Result loaded by the next stage using samplers. */
300 }
301 {
302 PassSimple &pass = horizon_denoise_ps_;
303 pass.init();
304 gpu::Shader *sh = inst_.shaders.static_shader_get(HORIZON_DENOISE);
305 pass.shader_set(sh);
306 pass.bind_texture("in_sh_0_tx", &horizon_radiance_tx_[0]);
307 pass.bind_texture("in_sh_1_tx", &horizon_radiance_tx_[1]);
308 pass.bind_texture("in_sh_2_tx", &horizon_radiance_tx_[2]);
309 pass.bind_texture("in_sh_3_tx", &horizon_radiance_tx_[3]);
310 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
311 pass.bind_image("out_sh_0_img", &horizon_radiance_denoised_tx_[0]);
312 pass.bind_image("out_sh_1_img", &horizon_radiance_denoised_tx_[1]);
313 pass.bind_image("out_sh_2_img", &horizon_radiance_denoised_tx_[2]);
314 pass.bind_image("out_sh_3_img", &horizon_radiance_denoised_tx_[3]);
315 pass.bind_ssbo("tiles_coord_buf", &horizon_tracing_tiles_buf_);
316 pass.bind_resources(inst_.uniform_data);
317 pass.bind_resources(inst_.sampling);
318 pass.bind_resources(inst_.hiz_buffer.front);
319 pass.dispatch(horizon_tracing_dispatch_buf_);
320 /* Result loaded by the next stage using samplers. */
322 }
323 {
324 PassSimple &pass = horizon_resolve_ps_;
325 pass.init();
326 gpu::Shader *sh = inst_.shaders.static_shader_get(HORIZON_RESOLVE);
327 pass.shader_set(sh);
328 pass.bind_texture("depth_tx", &depth_tx);
329 pass.bind_texture("horizon_radiance_0_tx", &horizon_radiance_denoised_tx_[0]);
330 pass.bind_texture("horizon_radiance_1_tx", &horizon_radiance_denoised_tx_[1]);
331 pass.bind_texture("horizon_radiance_2_tx", &horizon_radiance_denoised_tx_[2]);
332 pass.bind_texture("horizon_radiance_3_tx", &horizon_radiance_denoised_tx_[3]);
333 pass.bind_texture("screen_normal_tx", &downsampled_in_normal_tx_);
334 pass.bind_image("closure0_img", &horizon_scan_output_tx_[0]);
335 pass.bind_image("closure1_img", &horizon_scan_output_tx_[1]);
336 pass.bind_image("closure2_img", &horizon_scan_output_tx_[2]);
337 pass.bind_ssbo("tiles_coord_buf", &horizon_denoise_tiles_buf_);
338 pass.bind_resources(inst_.uniform_data);
339 pass.bind_resources(inst_.sampling);
340 pass.bind_resources(inst_.gbuffer);
341 pass.bind_resources(inst_.volume_probes);
342 pass.bind_resources(inst_.sphere_probes);
343 pass.dispatch(horizon_denoise_dispatch_buf_);
344 /* Can either be loaded by another denoising stage or by combined pass as texture. */
346 }
347
348 for (int i : IndexRange(3)) {
349 const bool use_denoise = (ray_tracing_options_.flag & RAYTRACE_EEVEE_USE_DENOISE);
350 const bool use_spatial_denoise = (ray_tracing_options_.denoise_stages &
352 use_denoise;
353 const bool use_temporal_denoise = (ray_tracing_options_.denoise_stages &
355 use_spatial_denoise;
356 const bool use_bilateral_denoise = (ray_tracing_options_.denoise_stages &
358 use_temporal_denoise;
359
360 data_.closure_index = i;
361 data_.resolution_scale = max_ii(1, power_of_2_max_i(ray_tracing_options_.resolution_scale));
362 data_.skip_denoise = !use_spatial_denoise;
363 inst_.manager->warm_shader_specialization(tile_classify_ps_);
364 inst_.manager->warm_shader_specialization(tile_compact_ps_);
365 inst_.manager->warm_shader_specialization(generate_ps_);
366 if (tracing_method_ == RAYTRACE_EEVEE_METHOD_SCREEN) {
367 if (inst_.planar_probes.enabled()) {
368 inst_.manager->warm_shader_specialization(trace_planar_ps_);
369 }
370 for (int j : IndexRange(2)) {
371 data_.trace_refraction = bool(j);
372 inst_.manager->warm_shader_specialization(trace_screen_ps_);
373 }
374 }
375 else {
376 inst_.manager->warm_shader_specialization(trace_fallback_ps_);
377 }
378 if (use_spatial_denoise) {
379 inst_.manager->warm_shader_specialization(denoise_spatial_ps_);
380 }
381 if (use_temporal_denoise) {
382 inst_.manager->warm_shader_specialization(denoise_temporal_ps_);
383 }
384 if (use_bilateral_denoise) {
385 inst_.manager->warm_shader_specialization(denoise_bilateral_ps_);
386 }
387 bool use_horizon_scan = ray_tracing_options_.trace_max_roughness < 1.0f;
388 if (use_horizon_scan) {
389 inst_.manager->warm_shader_specialization(horizon_schedule_ps_);
390 inst_.manager->warm_shader_specialization(horizon_setup_ps_);
391 inst_.manager->warm_shader_specialization(horizon_scan_ps_);
392 inst_.manager->warm_shader_specialization(horizon_denoise_ps_);
393 inst_.manager->warm_shader_specialization(horizon_resolve_ps_);
394 }
395 }
396}
397
399
400void RayTraceModule::debug_draw(View & /*view*/, gpu::FrameBuffer * /*view_fb*/) {}
401
403 gpu::Texture *screen_radiance_back_tx,
404 eClosureBits active_closures,
405 /* TODO(fclem): Maybe wrap these two in some other class. */
406 View &main_view,
407 View &render_view)
408{
409 using namespace blender::math;
410 BLI_assert(use_raytracing_);
411
412 screen_radiance_front_tx_ = rt_buffer.radiance_feedback_tx.is_valid() ?
413 rt_buffer.radiance_feedback_tx :
414 radiance_dummy_black_tx_;
415 screen_radiance_back_tx_ = screen_radiance_back_tx ? screen_radiance_back_tx :
416 screen_radiance_front_tx_;
417
418 RaytraceEEVEE options = ray_tracing_options_;
419
420 bool use_horizon_scan = options.trace_max_roughness < 1.0f;
421
422 const int resolution_scale = max_ii(1, power_of_2_max_i(options.resolution_scale));
423 const int horizon_resolution_scale = max_ii(
424 1, power_of_2_max_i(inst_.scene->eevee.fast_gi_resolution));
425
426 const int2 extent = inst_.film.render_extent_get();
427 const int2 tracing_res = math::divide_ceil(extent, int2(resolution_scale));
428 const int2 tracing_res_horizon = math::divide_ceil(extent, int2(horizon_resolution_scale));
429 const int2 dummy_extent(1, 1);
430 const int2 group_size(RAYTRACE_GROUP_SIZE);
431
432 const int2 denoise_tiles = divide_ceil(extent, group_size);
433 const int2 raytrace_tiles = divide_ceil(tracing_res, group_size);
434 const int2 raytrace_tiles_horizon = divide_ceil(tracing_res_horizon, group_size);
435 const int denoise_tile_count = denoise_tiles.x * denoise_tiles.y;
436 const int raytrace_tile_count = raytrace_tiles.x * raytrace_tiles.y;
437 const int raytrace_tile_count_horizon = raytrace_tiles_horizon.x * raytrace_tiles_horizon.y;
438 tile_classify_dispatch_size_ = int3(denoise_tiles, 1);
439 horizon_schedule_dispatch_size_ = int3(divide_ceil(raytrace_tiles_horizon, group_size), 1);
440 tile_compact_dispatch_size_ = int3(divide_ceil(raytrace_tiles, group_size), 1);
441 tracing_dispatch_size_ = int3(raytrace_tiles, 1);
442 horizon_tracing_dispatch_size_ = int3(raytrace_tiles_horizon, 1);
443
444 /* TODO(fclem): Use real max closure count from shader. */
445 const int closure_count = 3;
446 gpu::TextureFormat format = gpu::TextureFormat::RAYTRACE_TILEMASK_FORMAT;
448 tile_raytrace_denoise_tx_.ensure_2d_array(format, denoise_tiles, closure_count, usage_rw);
449 tile_raytrace_tracing_tx_.ensure_2d_array(format, raytrace_tiles, closure_count, usage_rw);
450 /* Kept as 2D array for compatibility with the tile compaction shader. */
451 tile_horizon_denoise_tx_.ensure_2d_array(format, denoise_tiles, 1, usage_rw);
452 tile_horizon_tracing_tx_.ensure_2d_array(format, raytrace_tiles_horizon, 1, usage_rw);
453
454 tile_raytrace_denoise_tx_.clear(uint4(0u));
455 tile_raytrace_tracing_tx_.clear(uint4(0u));
456 tile_horizon_denoise_tx_.clear(uint4(0u));
457 tile_horizon_tracing_tx_.clear(uint4(0u));
458
459 horizon_tracing_tiles_buf_.resize(ceil_to_multiple_u(raytrace_tile_count_horizon, 512));
460 horizon_denoise_tiles_buf_.resize(ceil_to_multiple_u(denoise_tile_count, 512));
461 raytrace_tracing_tiles_buf_.resize(ceil_to_multiple_u(raytrace_tile_count, 512));
462 raytrace_denoise_tiles_buf_.resize(ceil_to_multiple_u(denoise_tile_count, 512));
463
464 /* Data for tile classification. */
465 float roughness_mask_start = options.trace_max_roughness;
466 float roughness_mask_fade = 0.2f;
467 data_.roughness_mask_scale = 1.0 / roughness_mask_fade;
468 data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
469
470 /* Data for the radiance setup. */
471 data_.resolution_scale = resolution_scale;
472 data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
473 data_.radiance_persmat = render_view.persmat();
474 data_.full_resolution = extent;
475 data_.full_resolution_inv = 1.0f / float2(extent);
476
477 data_.horizon_resolution_scale = horizon_resolution_scale;
478 data_.horizon_resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) *
479 horizon_resolution_scale);
480 /* TODO(fclem): Eventually all uniform data is setup here. */
481
482 inst_.uniform_data.push_update();
483
485
486 GPU_debug_group_begin("Raytracing");
487
488 const bool has_active_closure = active_closures != CLOSURE_NONE;
489
490 if (has_active_closure) {
491 inst_.manager->submit(tile_classify_ps_);
492 }
493
494 data_.trace_refraction = screen_radiance_back_tx != nullptr;
495
496 for (int i = 0; i < 3; i++) {
497 result.closures[i] = trace(i, (closure_count > i), options, rt_buffer, main_view, render_view);
498 }
499
500 if (has_active_closure) {
501 if (use_horizon_scan) {
502 GPU_debug_group_begin("Horizon Scan");
503
504 downsampled_in_radiance_tx_.acquire(
505 tracing_res_horizon, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, usage_rw);
506 downsampled_in_normal_tx_.acquire(
507 tracing_res_horizon, gpu::TextureFormat::UNORM_10_10_10_2, usage_rw);
508
509 horizon_radiance_tx_[0].acquire(
510 tracing_res_horizon, gpu::TextureFormat::SFLOAT_16_16_16_16, usage_rw);
511 horizon_radiance_denoised_tx_[0].acquire(
512 tracing_res_horizon, gpu::TextureFormat::SFLOAT_16_16_16_16, usage_rw);
513 for (int i : IndexRange(1, 3)) {
514 horizon_radiance_tx_[i].acquire(
515 tracing_res_horizon, gpu::TextureFormat::UNORM_8_8_8_8, usage_rw);
516 horizon_radiance_denoised_tx_[i].acquire(
517 tracing_res_horizon, gpu::TextureFormat::UNORM_8_8_8_8, usage_rw);
518 }
519 for (int i : IndexRange(3)) {
520 horizon_scan_output_tx_[i] = result.closures[i];
521 }
522
523 horizon_tracing_dispatch_buf_.clear_to_zero();
524 horizon_denoise_dispatch_buf_.clear_to_zero();
525 inst_.manager->submit(horizon_schedule_ps_);
526
527 inst_.manager->submit(horizon_setup_ps_, render_view);
528 inst_.manager->submit(horizon_scan_ps_, render_view);
529 inst_.manager->submit(horizon_denoise_ps_, render_view);
530 inst_.manager->submit(horizon_resolve_ps_, render_view);
531
532 for (int i : IndexRange(4)) {
533 horizon_radiance_tx_[i].release();
534 horizon_radiance_denoised_tx_[i].release();
535 }
536 downsampled_in_radiance_tx_.release();
537 downsampled_in_normal_tx_.release();
538
540 }
541 }
542
544
545 rt_buffer.history_persmat = render_view.persmat();
546
547 return result;
548}
549
550RayTraceResultTexture RayTraceModule::trace(
551 int closure_index,
552 bool active_layer,
554 RayTraceBuffer &rt_buffer,
555 /* TODO(fclem): Maybe wrap these two in some other class. */
556 View &main_view,
557 View &render_view)
558{
559 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[closure_index];
560
561 if (!active_layer) {
562 /* Early out. Release persistent buffers. Still acquire one dummy resource for validation. */
563 denoise_buf->denoised_spatial_tx.acquire(int2(1),
564 gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT);
565 denoise_buf->radiance_history_tx.free();
566 denoise_buf->variance_history_tx.free();
567 denoise_buf->tilemask_history_tx.free();
568 return {denoise_buf->denoised_spatial_tx};
569 }
570
571 const int resolution_scale = max_ii(1, power_of_2_max_i(options.resolution_scale));
572
573 const int2 extent = inst_.film.render_extent_get();
574 const int2 tracing_res = math::divide_ceil(extent, int2(resolution_scale));
575
576 renderbuf_depth_view_ = inst_.render_buffers.depth_tx;
577
578 const bool use_denoise = (options.flag & RAYTRACE_EEVEE_USE_DENOISE);
579 const bool use_spatial_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_SPATIAL) &&
580 use_denoise;
581 const bool use_temporal_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_TEMPORAL) &&
582 use_spatial_denoise;
583 const bool use_bilateral_denoise = (options.denoise_stages & RAYTRACE_EEVEE_DENOISE_BILATERAL) &&
584 use_temporal_denoise;
585
587
588 GPU_debug_group_begin("Raytracing");
589
590 data_.thickness = options.screen_trace_thickness;
591 data_.quality = 1.0f - 0.95f * options.screen_trace_quality;
592
593 float roughness_mask_start = options.trace_max_roughness;
594 float roughness_mask_fade = 0.2f;
595 data_.roughness_mask_scale = 1.0 / roughness_mask_fade;
596 data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
597
598 data_.resolution_scale = resolution_scale;
599 data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
600 data_.history_persmat = denoise_buf->history_persmat;
601 data_.radiance_persmat = render_view.persmat();
602 data_.full_resolution = extent;
603 data_.full_resolution_inv = 1.0f / float2(extent);
604 data_.skip_denoise = !use_spatial_denoise;
605 data_.closure_index = closure_index;
607
608 /* Ray setup. */
609 raytrace_tracing_dispatch_buf_.clear_to_zero();
610 raytrace_denoise_dispatch_buf_.clear_to_zero();
611 inst_.manager->submit(tile_compact_ps_);
612
613 {
614 /* Tracing rays. */
615 ray_data_tx_.acquire(tracing_res, gpu::TextureFormat::SFLOAT_16_16_16_16);
616 ray_time_tx_.acquire(tracing_res, gpu::TextureFormat::RAYTRACE_RAYTIME_FORMAT);
617 ray_radiance_tx_.acquire(tracing_res, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT);
618
619 inst_.manager->submit(generate_ps_, render_view);
620 if (tracing_method_ == RAYTRACE_EEVEE_METHOD_SCREEN) {
621 if (inst_.planar_probes.enabled()) {
622 inst_.manager->submit(trace_planar_ps_, render_view);
623 }
624 inst_.manager->submit(trace_screen_ps_, render_view);
625 }
626 else {
627 inst_.manager->submit(trace_fallback_ps_, render_view);
628 }
629 }
630
631 RayTraceResultTexture result;
632
633 /* Spatial denoise pass is required to resolve at least one ray per pixel. */
634 {
635 denoise_buf->denoised_spatial_tx.acquire(extent, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT);
636 hit_variance_tx_.acquire(use_temporal_denoise ? extent : int2(1),
637 gpu::TextureFormat::RAYTRACE_VARIANCE_FORMAT);
638 hit_depth_tx_.acquire(use_temporal_denoise ? extent : int2(1), gpu::TextureFormat::SFLOAT_32);
639 denoised_spatial_tx_ = denoise_buf->denoised_spatial_tx;
640
641 inst_.manager->submit(denoise_spatial_ps_, render_view);
642
643 result = {denoise_buf->denoised_spatial_tx};
644 }
645
646 ray_data_tx_.release();
647 ray_time_tx_.release();
648 ray_radiance_tx_.release();
649
650 if (use_temporal_denoise) {
651 denoise_buf->denoised_temporal_tx.acquire(
652 extent, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, usage_rw);
653 denoise_variance_tx_.acquire(use_bilateral_denoise ? extent : int2(1),
654 gpu::TextureFormat::RAYTRACE_VARIANCE_FORMAT,
655 usage_rw);
656 denoise_buf->variance_history_tx.ensure_2d(gpu::TextureFormat::RAYTRACE_VARIANCE_FORMAT,
657 use_bilateral_denoise ? extent : int2(1),
658 usage_rw);
659 denoise_buf->tilemask_history_tx.ensure_2d_array(gpu::TextureFormat::RAYTRACE_TILEMASK_FORMAT,
660 tile_raytrace_denoise_tx_.size().xy(),
661 tile_raytrace_denoise_tx_.size().z,
662 usage_rw);
663
664 if (denoise_buf->radiance_history_tx.ensure_2d(
665 gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, extent, usage_rw) ||
666 denoise_buf->valid_history == false)
667 {
668 /* If viewport resolution changes, do not try to use history. */
669 denoise_buf->tilemask_history_tx.clear(uint4(0u));
670 }
671
672 radiance_history_tx_ = denoise_buf->radiance_history_tx;
673 variance_history_tx_ = denoise_buf->variance_history_tx;
674 tilemask_history_tx_ = denoise_buf->tilemask_history_tx;
675 denoised_temporal_tx_ = denoise_buf->denoised_temporal_tx;
676
677 inst_.manager->submit(denoise_temporal_ps_, render_view);
678
679 /* Save view-projection matrix for next reprojection. */
680 denoise_buf->history_persmat = main_view.persmat();
681 /* Radiance will be swapped with history in #RayTraceResult::release().
682 * Variance is swapped with history after bilateral denoise.
683 * It keeps data-flow easier to follow. */
684 result = {denoise_buf->denoised_temporal_tx, denoise_buf->radiance_history_tx};
685 /* Not referenced by result anymore. */
686 denoise_buf->denoised_spatial_tx.release();
687
688 GPU_texture_copy(denoise_buf->tilemask_history_tx, tile_raytrace_denoise_tx_);
689 }
690
691 /* Only use history buffer for the next frame if temporal denoise was used by the current one. */
692 denoise_buf->valid_history = use_temporal_denoise;
693
694 hit_variance_tx_.release();
695 hit_depth_tx_.release();
696
697 if (use_bilateral_denoise) {
698 denoise_buf->denoised_bilateral_tx.acquire(
699 extent, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, usage_rw);
700 denoised_bilateral_tx_ = denoise_buf->denoised_bilateral_tx;
701
702 inst_.manager->submit(denoise_bilateral_ps_, render_view);
703
704 /* Swap after last use. */
706 TextureFromPool::swap(denoise_variance_tx_, denoise_buf->variance_history_tx);
707
708 result = {denoise_buf->denoised_bilateral_tx};
709 /* Not referenced by result anymore. */
710 denoise_buf->denoised_temporal_tx.release();
711 }
712
713 denoise_variance_tx_.release();
714
716
717 return result;
718}
719
721{
722 const int2 extent = inst_.film.render_extent_get();
724
726 for (int i = 0; i < 3; i++) {
727 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
728 denoise_buf->denoised_bilateral_tx.acquire(
729 extent, gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, usage_rw);
730 result.closures[i] = {denoise_buf->denoised_bilateral_tx};
731 }
732 return result;
733}
734
736{
738
740 for (int i = 0; i < 3; i++) {
741 RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
742 denoise_buf->denoised_bilateral_tx.acquire(
743 int2(1), gpu::TextureFormat::RAYTRACE_RADIANCE_FORMAT, usage_rw);
744 result.closures[i] = {denoise_buf->denoised_bilateral_tx};
745 }
746 return result;
747}
748
749
750} // 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
@ RAYTRACE_EEVEE_USE_DENOISE
@ FAST_GI_AO_ONLY
@ SCE_EEVEE_FAST_GI_ENABLED
@ SCE_EEVEE_SSR_ENABLED
@ 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(blender::gpu::Texture *dst, blender::gpu::Texture *src)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
BMesh const char void * data
void submit(PassSimple &pass, View &view)
static void swap(TextureFromPool &a, Texture &b)
void acquire(int2 extent, blender::gpu::TextureFormat format, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL)
bool ensure_2d_array(blender::gpu::TextureFormat format, int2 extent, int layers, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
void clear(float4 values)
bool ensure_2d(blender::gpu::TextureFormat 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_resources(U &resources)
Definition draw_pass.hh:449
void shader_set(gpu::Shader *shader)
void bind_texture(const char *name, gpu::Texture *texture, GPUSamplerState state=sampler_auto)
void specialize_constant(gpu::Shader *shader, const char *name, const float &data)
void bind_image(const char *name, gpu::Texture *image)
void dispatch(int group_len)
void barrier(GPUBarrier type)
void bind_ssbo(const char *name, gpu::StorageBuf *buffer)
int2 render_extent_get() const
PlanarProbeModule planar_probes
UniformDataModule uniform_data
RayTraceResult render(RayTraceBuffer &rt_buffer, gpu::Texture *screen_radiance_back_tx, eClosureBits active_closures, View &main_view, View &render_view)
RayTraceResult alloc_only(RayTraceBuffer &rt_buffer)
void debug_draw(View &view, gpu::FrameBuffer *view_fb)
RayTraceResult alloc_dummy(RayTraceBuffer &rt_buffer)
float2 rng_2d_get(eSamplingDimension starting_dimension) const
CCL_NAMESPACE_BEGIN struct Options options
#define RBUFS_UTILITY_TEX_SLOT
#define RAYTRACE_GROUP_SIZE
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