20 auto fs_ssr_fidelityfx = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_fidelityfx.sc");
23 auto fs_ssr_temporal_resolve = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_temporal_resolve.sc");
26 auto fs_ssr_composite = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_composite.sc");
29 auto cs_ssr_blur = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/cs_ssr_blur.sc");
32 auto cs_ssr_spatial_denoise = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/cs_ssr_spatial_denoise.sc");
35 fidelityfx_pixel_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_fidelityfx);
36 fidelityfx_pixel_program_.cache_uniforms();
39 temporal_resolve_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_temporal_resolve);
40 temporal_resolve_program_.cache_uniforms();
43 composite_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_composite);
44 composite_program_.cache_uniforms();
47 blur_compute_program_.program = std::make_unique<gpu_program>(cs_ssr_blur);
48 blur_compute_program_.cache_uniforms();
51 spatial_denoise_compute_program_.program = std::make_unique<gpu_program>(cs_ssr_spatial_denoise);
52 spatial_denoise_compute_program_.cache_uniforms();
55 bool all_valid = fidelityfx_pixel_program_.is_valid() && temporal_resolve_program_.is_valid() &&
56 composite_program_.is_valid() && blur_compute_program_.is_valid() &&
57 spatial_denoise_compute_program_.is_valid();
73 auto ref_sz = reference->get_size();
74 auto ref_format = gfx::texture_format::RGBA16F;
76 auto& ssr_output_tex = rview.tex_get_or_emplace(
"SSR_OUTPUT");
79 ssr_output_tex.reset();
80 ssr_output_tex = std::make_shared<gfx::texture>(ref_sz.width,
85 BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
86 BGFX_SAMPLER_V_CLAMP);
89 auto& ssr_output_fbo = rview.fbo_get_or_emplace(
"SSR_OUTPUT");
92 ssr_output_fbo.reset();
93 ssr_output_fbo = std::make_shared<gfx::frame_buffer>();
94 ssr_output_fbo->populate({ssr_output_tex});
97 return ssr_output_fbo;
105 const auto ref_format = gfx::texture_format::RGBA16F;
107 auto& ssr_curr_tex = rview.tex_get_or_emplace(
"SSR_CURR");
110 ssr_curr_tex.reset();
111 ssr_curr_tex = std::make_shared<gfx::texture>(target_size.width,
116 BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
117 BGFX_SAMPLER_V_CLAMP);
120 auto& ssr_curr_fbo = rview.fbo_get_or_emplace(
"SSR_CURR");
123 ssr_curr_fbo.reset();
124 ssr_curr_fbo = std::make_shared<gfx::frame_buffer>();
125 ssr_curr_fbo->populate({ssr_curr_tex});
136 const auto ref_format = gfx::texture_format::RGBA16F;
138 auto& history_tex = rview.tex_get_or_emplace(
"SSR_HISTORY");
142 history_tex = std::make_shared<gfx::texture>(target_size.width,
147 BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
148 BGFX_SAMPLER_V_CLAMP);
159 const auto ref_format = gfx::texture_format::RGBA16F;
161 auto& temp_tex = rview.tex_get_or_emplace(
"SSR_HISTORY_TEMP");
165 temp_tex = std::make_shared<gfx::texture>(target_size.width,
170 BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
171 BGFX_SAMPLER_V_CLAMP);
174 auto& temp_fbo = rview.fbo_get_or_emplace(
"SSR_HISTORY_TEMP");
178 temp_fbo = std::make_shared<gfx::frame_buffer>();
179 temp_fbo->populate({temp_tex});
194 return run_fidelityfx(rview, params);
200 return run_fidelityfx_three_pass(rview, params);
216 if(!blur_compute_program_.program || !blur_compute_program_.program->is_valid())
221 auto input_size = input_color->get_size();
224 auto& blurred_tex = rview.tex_get_or_emplace(
"SSR_BLURRED_COLOR");
228 blurred_tex = std::make_shared<gfx::texture>(input_size.width,
232 gfx::texture_format::RGBA16F,
233 BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP |
234 BGFX_TEXTURE_COMPUTE_WRITE | BGFX_TEXTURE_RT);
237 const uint32_t num_mips =
settings.cone_tracing.max_mip_level + 1;
241 for(
int mip = 0; mip < num_mips; ++mip)
244 int mip_width = (input_size.width >> mip) > 1 ? (input_size.width >> mip) : 1;
245 int mip_height = (input_size.height >> mip) > 1 ? (input_size.height >> mip) : 1;
248 float sigma =
settings.cone_tracing.blur_base_sigma;
251 blur_compute_program_.program->begin();
257 gfx::set_image(1, input_color->native_handle(), 0, bgfx::Access::Read);
262 gfx::set_image(1, blurred_tex->native_handle(), mip - 1, bgfx::Access::Read);
265 float blur_params[4] = {float(mip), sigma, 0.0f, 0.0f};
269 gfx::set_image(0, blurred_tex->native_handle(), mip, bgfx::Access::Write);
271 gfx::set_texture(blur_compute_program_.s_normal, 2, g_buffer->get_texture(1));
274 uint32_t num_groups_x = (mip_width + 7) / 8;
275 uint32_t num_groups_y = (mip_height + 7) / 8;
276 gfx::dispatch(pass.
id, blur_compute_program_.program->native_handle(), num_groups_x, num_groups_y, 1);
278 blur_compute_program_.program->end();
285 const std::string&
name,
291 auto& denoised_tex = rview.tex_get_or_emplace(
name);
294 denoised_tex.reset();
295 denoised_tex = std::make_shared<gfx::texture>(target_size.width,
299 gfx::texture_format::RGBA16F,
300 BGFX_TEXTURE_COMPUTE_WRITE | BGFX_TEXTURE_RT |
301 BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
304 auto& denoised_fbo = rview.fbo_get_or_emplace(
name);
307 denoised_fbo.reset();
308 denoised_fbo = std::make_shared<gfx::frame_buffer>();
309 denoised_fbo->populate({denoised_tex});
320 if(!spatial_denoise_compute_program_.is_valid())
327 const int num_passes = std::clamp(
settings.spatial_denoise.passes, 1, 5);
334 auto sz = fb_a->get_size();
335 const uint32_t gx = (sz.width + 7) / 8;
336 const uint32_t gy = (sz.height + 7) / 8;
338 auto src_tex = ssr_curr->get_texture();
341 for(
int i = 0; i < num_passes; ++i)
345 spatial_denoise_compute_program_.program->begin();
348 gfx::set_image(1, dst_fb->get_texture()->native_handle(), 0, bgfx::Access::Write);
349 gfx::set_texture(spatial_denoise_compute_program_.s_normal, 2, g_buffer->get_texture(1));
350 gfx::set_texture(spatial_denoise_compute_program_.s_depth, 3, g_buffer->get_texture(4));
352 float denoise_params[4] = {
354 settings.spatial_denoise.depth_sigma,
355 settings.spatial_denoise.normal_power,
356 settings.spatial_denoise.luma_sigma};
357 gfx::set_uniform(spatial_denoise_compute_program_.u_denoise_params, denoise_params);
359 gfx::dispatch(pass.
id, spatial_denoise_compute_program_.program->native_handle(), gx, gy, 1);
361 spatial_denoise_compute_program_.program->end();
363 src_tex = dst_fb->get_texture();
364 dst_fb = (dst_fb == fb_a) ? fb_b : fb_a;
369 return (dst_fb == fb_a) ? fb_b : fb_a;
376 auto ssr_curr_fb = run_ssr_trace(rview, params);
384 auto temporal_input_fb = ssr_curr_fb;
385 if(params.settings.fidelityfx.enable_spatial_denoise)
387 temporal_input_fb = run_spatial_denoise(rview, ssr_curr_fb, params.g_buffer, params.settings.fidelityfx);
391 rview.fbo_remove(
"SSR_DENOISED_A");
392 rview.tex_remove(
"SSR_DENOISED_A");
393 rview.fbo_remove(
"SSR_DENOISED_B");
394 rview.tex_remove(
"SSR_DENOISED_B");
398 auto ssr_history_fb =
399 run_temporal_resolve(rview, temporal_input_fb, params.g_buffer, params.cam, params.settings.fidelityfx);
408 run_composite(rview, ssr_history_fb, ssr_curr_fb, params.output, params.g_buffer, params.output);
416 const auto trace_res = params.settings.fidelityfx.resolution;
417 auto ssr_curr_fbo = create_or_update_ssr_curr_fb(rview, params.g_buffer, trace_res);
421 if(params.settings.fidelityfx.enable_cone_tracing && params.previous_frame)
423 blurred_color_buffer =
424 generate_blurred_color_buffer(rview, params.previous_frame, params.g_buffer, params.settings.fidelityfx);
428 rview.tex_remove(
"SSR_BLURRED_COLOR");
437 pass.
bind(ssr_curr_fbo.get());
438 pass.
set_view_proj(params.cam->get_view(), params.cam->get_projection());
441 fidelityfx_pixel_program_.program->begin();
444 gfx::set_texture(fidelityfx_pixel_program_.s_color, 0, params.previous_frame);
445 gfx::set_texture(fidelityfx_pixel_program_.s_normal, 1, params.g_buffer->get_texture(1));
446 gfx::set_texture(fidelityfx_pixel_program_.s_depth, 2, params.g_buffer->get_texture(4));
450 auto cone_tracing_texture = blurred_color_buffer ? blurred_color_buffer : params.previous_frame;
451 gfx::set_texture(fidelityfx_pixel_program_.s_color_blurred, 4, cone_tracing_texture);
454 float ssr_params[4] = {float(params.settings.fidelityfx.max_steps),
455 params.settings.fidelityfx.depth_tolerance,
456 float(params.settings.fidelityfx.max_rays),
457 params.settings.fidelityfx.brightness};
468 auto ssr_size = ssr_curr_fbo->get_size();
469 auto g_buffer_size = params.g_buffer->get_size();
470 const float ssr_scale_x = float(g_buffer_size.width) / float(ssr_size.width);
471 const float ssr_scale_y = float(g_buffer_size.height) / float(ssr_size.height);
474 float hiz_params[4] = {0.0f, 0.0f, ssr_scale_x, ssr_scale_y};
475 if(params.hiz_buffer)
477 hiz_params[0] = float(params.hiz_buffer->info.width);
478 hiz_params[1] = float(params.hiz_buffer->info.height);
483 float fade_params[4] = {params.settings.fidelityfx.fade_in_start,
484 params.settings.fidelityfx.fade_in_end,
485 params.settings.fidelityfx.roughness_depth_tolerance,
486 params.settings.fidelityfx.facing_reflections_fading};
490 float cone_params[4] = {
491 params.settings.fidelityfx.cone_tracing.cone_angle_bias,
492 float(params.settings.fidelityfx.cone_tracing.max_mip_level),
494 float(params.settings.fidelityfx.enable_cone_tracing ? 1.0f : 0.0f)
499 auto prev_view_proj = params.cam->get_prev_view_projection();
500 gfx::set_uniform(fidelityfx_pixel_program_.u_prev_view_proj, prev_view_proj.get_matrix());
507 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
508 gfx::submit(pass.
id, fidelityfx_pixel_program_.program->native_handle());
512 fidelityfx_pixel_program_.program->end();
524 if(!temporal_resolve_program_.is_valid())
531 auto old_history = rview.tex_safe_get(
"SSR_HISTORY");
537 if(history_tex != old_history)
540 gfx::blit(
blit_pass.id, history_tex->native_handle(), 0, 0, ssr_curr->get_texture()->native_handle(), 0, 0);
550 pass.
bind(temp_fbo.get());
554 temporal_resolve_program_.program->begin();
557 gfx::set_texture(temporal_resolve_program_.s_ssr_curr, 0, ssr_curr->get_texture());
559 gfx::set_texture(temporal_resolve_program_.s_normal, 2, g_buffer->get_texture(1));
560 gfx::set_texture(temporal_resolve_program_.s_depth, 3, g_buffer->get_texture(4));
563 float temporal_params[4] = {
settings.enable_temporal_accumulation ? 1.0f : 0.0f,
566 settings.temporal.roughness_sensitivity};
567 gfx::set_uniform(temporal_resolve_program_.u_temporal_params, temporal_params);
570 float motion_params[4] = {
571 settings.temporal.motion_scale_pixels,
572 settings.temporal.normal_dot_threshold,
573 float(
settings.temporal.max_accum_frames),
579 auto history_size = history_tex->get_size();
580 auto g_buffer_size = g_buffer->get_size();
581 const float ssr_scale_x = float(g_buffer_size.width) / float(history_size.width);
582 const float ssr_scale_y = float(g_buffer_size.height) / float(history_size.height);
584 float fade_params[4] = {
settings.fade_in_start,
settings.fade_in_end, ssr_scale_x, ssr_scale_y};
588 auto prev_view_proj = cam->get_prev_view_projection();
589 gfx::set_uniform(temporal_resolve_program_.u_prev_view_proj, prev_view_proj.get_matrix());
593 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
594 gfx::submit(pass.
id, temporal_resolve_program_.program->native_handle());
598 temporal_resolve_program_.program->end();
605 gfx::blit(
blit_pass.id, history_tex->native_handle(), 0, 0, temp_fbo->get_texture()->native_handle(), 0, 0);
617 if(!composite_program_.is_valid())
623 auto actual_output = create_or_update_output_fb(rview, g_buffer, output);
631 pass.
bind(actual_output.get());
634 composite_program_.program->begin();
637 gfx::set_texture(composite_program_.s_ssr_history, 0, ssr_history->get_texture());
638 gfx::set_texture(composite_program_.s_ssr_curr, 1, ssr_curr->get_texture());
644 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A |
645 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
646 gfx::submit(pass.
id, composite_program_.program->native_handle());
650 composite_program_.program->end();
653 return actual_output;
std::shared_ptr< frame_buffer > ptr
void tex_remove(const hpp::string_view &id)
void fbo_remove(const hpp::string_view &id)
Manages assets, including loading, unloading, and storage.
auto get_asset(const std::string &key, load_flags flags=load_flags::standard, load_mode mode=load_mode::immediate) -> asset_handle< T >
Gets an asset by its key.
Class representing a camera. Contains functionality for manipulating and updating a camera....
auto run_ssr_trace(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the SSR trace pass only. Returns SSR current frame buffer.
auto generate_blurred_color_buffer(gfx::render_view &rview, const gfx::texture::ptr &input_color, const gfx::frame_buffer::ptr &g_buffer, const fidelityfx_ssr_settings &settings) -> gfx::texture::ptr
Generates blurred color buffer with mip chain for cone tracing.
auto run_fidelityfx(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the FidelityFX SSR pass. Returns the actual output framebuffer.
auto run_fidelityfx_three_pass(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the three-pass SSR pipeline (trace, temporal resolve, composite)
auto run_composite(gfx::render_view &rview, const gfx::frame_buffer::ptr &ssr_history, const gfx::frame_buffer::ptr &ssr_curr, const gfx::frame_buffer::ptr &probe_buffer, const gfx::frame_buffer::ptr &g_buffer, const gfx::frame_buffer::ptr &output) -> gfx::frame_buffer::ptr
Executes the composite pass. Returns final blended output.
auto init(rtti::context &ctx) -> bool
Must be called once (after bgfx::init() and after asset_manager is registered in context).
auto run(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the SSR pass. Returns the actual output framebuffer.
auto run_spatial_denoise(gfx::render_view &rview, const gfx::frame_buffer::ptr &ssr_curr, const gfx::frame_buffer::ptr &g_buffer, const fidelityfx_ssr_settings &settings) -> gfx::frame_buffer::ptr
Executes spatial denoise on SSR result before temporal resolve.
auto run_temporal_resolve(gfx::render_view &rview, const gfx::frame_buffer::ptr &ssr_curr, const gfx::frame_buffer::ptr &g_buffer, const camera *cam, const fidelityfx_ssr_settings &settings) -> gfx::frame_buffer::ptr
Executes the temporal resolve pass. Returns updated SSR history buffer.
void release_resources(gfx::render_view &rview)
Releases all GPU resources owned by this pass from the render_view.
void dispatch(view_id _id, program_handle _handle, uint32_t _numX, uint32_t _numY, uint32_t _numZ)
void submit(view_id _id, program_handle _handle, int32_t _depth, bool _preserveState)
void set_state(uint64_t _state, uint32_t _rgba)
auto clip_fullscreen_triangle(float depth, float width, float height) -> uint64_t
auto needs_recreate(const gfx::frame_buffer::ptr &fbo, const usize32_t &size) -> bool
void blit(view_id _id, texture_handle _dst, uint16_t _dstX, uint16_t _dstY, texture_handle _src, uint16_t _srcX, uint16_t _srcY, uint16_t _width, uint16_t _height)
void discard(uint8_t _flags)
void set_image(uint8_t _stage, texture_handle _handle, uint8_t _mip, access _access, texture_format _format)
void set_uniform(uniform_handle _handle, const void *_value, uint16_t _num)
uint32_t get_render_frame()
auto clip_quad(float depth, float width, float height) -> uint64_t
void set_texture(uint8_t _stage, uniform_handle _sampler, texture_handle _handle, uint32_t _flags)
auto compute_trace_size(const usize32_t &ref, trace_resolution res) -> usize32_t
Computes the trace-target size from a full-resolution reference, clamped to 1x1 min.
#define APP_SCOPE_PERF(name_literal)
Create a scoped performance timer that records to the timeline profiler. Only accepts string literals...
void set_view_proj(const float *v, const float *p)
static void push_scope(const char *name)
void bind(const frame_buffer *fb=nullptr) const