Files
test2/source/blender/draw/engines/eevee/eevee_raytrace.hh
Clément Foucault 894c7fa4e2 EEVEE: Remove EEVEE Next mention inside the code
This only changes file and function names.
The EEVEE identifier is still `BLENDER_EEVEE_NEXT`.

No functional changes.
2025-03-17 15:37:04 +01:00

289 lines
11 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup eevee
*
* The ray-tracing module class handles ray generation, scheduling, tracing and denoising.
*/
#pragma once
#include "DNA_scene_types.h"
#include "DRW_render.hh"
#include "eevee_shader_shared.hh"
namespace blender::eevee {
class Instance;
/* -------------------------------------------------------------------- */
/** \name Ray-tracing Buffers
*
* Contain persistent data used for temporal denoising. Similar to \class GBuffer but only contains
* persistent data.
* \{ */
/**
* Contain persistent buffer that need to be stored per view, per deferred layer.
*/
struct RayTraceBuffer {
/** Set of buffers that need to be allocated for each ray type. */
struct DenoiseBuffer {
/* Persistent history buffers. */
Texture radiance_history_tx = {"radiance_tx"};
Texture variance_history_tx = {"variance_tx"};
/* Map of tiles that were processed inside the history buffer. */
Texture tilemask_history_tx = {"tilemask_tx"};
/** Perspective matrix for which the history buffers were recorded. */
float4x4 history_persmat;
/** True if history buffer was used last frame and can be re-projected. */
bool valid_history = false;
/**
* Textures containing the ray hit radiance denoised (full-res). One of them is result_tx.
* One might become result buffer so it need instantiation by closure type to avoid reuse.
*/
TextureFromPool denoised_spatial_tx = {"denoised_spatial_tx"};
TextureFromPool denoised_temporal_tx = {"denoised_temporal_tx"};
TextureFromPool denoised_bilateral_tx = {"denoised_bilateral_tx"};
};
/**
* One for each closure. Not to be mistaken with deferred layer type.
*/
DenoiseBuffer closures[3];
/**
* Radiance feedback of the deferred layer for next sample's reflection or next layer's
* transmission.
*/
Texture radiance_feedback_tx = {"radiance_feedback_tx"};
/**
* Perspective matrix for which the radiance feedback buffer was recorded.
* Can be different from de-noise buffer's history matrix.
*/
float4x4 history_persmat;
GPUTexture *feedback_ensure(bool is_dummy, int2 extent)
{
eGPUTextureUsage usage_rw = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
if (radiance_feedback_tx.ensure_2d(GPU_RGBA16F, is_dummy ? int2(1) : extent, usage_rw)) {
radiance_feedback_tx.clear(float4(0.0f));
}
return radiance_feedback_tx;
}
};
/**
* Contains the result texture.
* The result buffer is usually short lived and is kept in a TextureFromPool managed by the mode.
* This structure contains a reference to it so that it can be freed after use by the caller.
*/
class RayTraceResultTexture {
private:
/** Result is in a temporary texture that needs to be released. */
TextureFromPool *result_ = nullptr;
/** Value of `result_->tx_` that can be referenced in advance. */
GPUTexture *tx_ = nullptr;
/** History buffer to swap the temporary texture that does not need to be released. */
Texture *history_ = nullptr;
public:
RayTraceResultTexture() = default;
RayTraceResultTexture(TextureFromPool &result) : result_(result.ptr()), tx_(result){};
RayTraceResultTexture(TextureFromPool &result, Texture &history)
: result_(result.ptr()), tx_(result), history_(history.ptr()){};
operator GPUTexture *() const
{
BLI_assert(tx_ != nullptr);
return tx_;
}
GPUTexture **operator&()
{
return &tx_;
}
void release()
{
if (history_) {
/* Swap after last use. */
TextureFromPool::swap(*result_, *history_);
}
/* NOTE: This releases the previous history. */
result_->release();
}
};
struct RayTraceResult {
RayTraceResultTexture closures[3];
void release()
{
for (int i = 0; i < 3; i++) {
closures[i].release();
}
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Ray-tracing
* \{ */
class RayTraceModule {
private:
Instance &inst_;
draw::PassSimple tile_classify_ps_ = {"TileClassify"};
draw::PassSimple tile_compact_ps_ = {"TileCompact"};
draw::PassSimple generate_ps_ = {"RayGenerate"};
draw::PassSimple trace_planar_ps_ = {"Trace.Planar"};
draw::PassSimple trace_screen_ps_ = {"Trace.Screen"};
draw::PassSimple trace_fallback_ps_ = {"Trace.Fallback"};
draw::PassSimple denoise_spatial_ps_ = {"DenoiseSpatial"};
draw::PassSimple denoise_temporal_ps_ = {"DenoiseTemporal"};
draw::PassSimple denoise_bilateral_ps_ = {"DenoiseBilateral"};
draw::PassSimple horizon_schedule_ps_ = {"HorizonScan.Schedule"};
draw::PassSimple horizon_setup_ps_ = {"HorizonScan.Setup"};
draw::PassSimple horizon_scan_ps_ = {"HorizonScan.Trace"};
draw::PassSimple horizon_denoise_ps_ = {"HorizonScan.Denoise"};
draw::PassSimple horizon_resolve_ps_ = {"HorizonScan.Resolve"};
/** Dispatch with enough tiles for the whole screen. */
int3 tile_classify_dispatch_size_ = int3(1);
/** Dispatch with enough tiles for the tile mask. */
int3 tile_compact_dispatch_size_ = int3(1);
int3 horizon_schedule_dispatch_size_ = int3(1);
/** Dispatch with enough tiles for the tracing resolution. */
int3 tracing_dispatch_size_ = int3(1);
int3 horizon_tracing_dispatch_size_ = int3(1);
/** 2D tile mask to check which unused adjacent tile we need to clear and which tile we need to
* dispatch for each work type. */
Texture tile_raytrace_denoise_tx_ = {"tile_raytrace_denoise_tx_"};
Texture tile_raytrace_tracing_tx_ = {"tile_raytrace_tracing_tx_"};
Texture tile_horizon_denoise_tx_ = {"tile_horizon_denoise_tx_"};
Texture tile_horizon_tracing_tx_ = {"tile_horizon_tracing_tx_"};
/** Indirect dispatch rays. Avoid dispatching work-groups that will not trace anything. */
DispatchIndirectBuf raytrace_tracing_dispatch_buf_ = {"raytrace_tracing_dispatch_buf_"};
/** Indirect dispatch denoise full-resolution tiles. */
DispatchIndirectBuf raytrace_denoise_dispatch_buf_ = {"raytrace_denoise_dispatch_buf_"};
/** Indirect dispatch horizon scan. Avoid dispatching work-groups that will not scan anything. */
DispatchIndirectBuf horizon_tracing_dispatch_buf_ = {"horizon_tracing_dispatch_buf_"};
/** Indirect dispatch denoise full-resolution tiles. */
DispatchIndirectBuf horizon_denoise_dispatch_buf_ = {"horizon_denoise_dispatch_buf_"};
/** Pointer to the texture to store the result of horizon scan in. */
GPUTexture *horizon_scan_output_tx_[3] = {nullptr};
/** Tile buffer that contains tile coordinates. */
RayTraceTileBuf raytrace_tracing_tiles_buf_ = {"raytrace_tracing_tiles_buf_"};
RayTraceTileBuf raytrace_denoise_tiles_buf_ = {"raytrace_denoise_tiles_buf_"};
RayTraceTileBuf horizon_tracing_tiles_buf_ = {"horizon_tracing_tiles_buf_"};
RayTraceTileBuf horizon_denoise_tiles_buf_ = {"horizon_denoise_tiles_buf_"};
/** Texture containing the ray direction and PDF. */
TextureFromPool ray_data_tx_ = {"ray_data_tx"};
/** Texture containing the ray hit time. */
TextureFromPool ray_time_tx_ = {"ray_data_tx"};
/** Texture containing the ray hit radiance (tracing-res). */
TextureFromPool ray_radiance_tx_ = {"ray_radiance_tx"};
/** Texture containing the horizon local radiance. */
TextureFromPool horizon_radiance_tx_[4] = {{"horizon_radiance_tx_"}};
TextureFromPool horizon_radiance_denoised_tx_[4] = {{"horizon_radiance_denoised_tx_"}};
/** Texture containing the input screen radiance but re-projected. */
TextureFromPool downsampled_in_radiance_tx_ = {"downsampled_in_radiance_tx_"};
/** Texture containing the view space normal. The BSDF normal is arbitrarily chosen. */
TextureFromPool downsampled_in_normal_tx_ = {"downsampled_in_normal_tx_"};
/** Textures containing the ray hit radiance denoised (full-res). One of them is result_tx. */
GPUTexture *denoised_spatial_tx_ = nullptr;
GPUTexture *denoised_temporal_tx_ = nullptr;
GPUTexture *denoised_bilateral_tx_ = nullptr;
/** Ray hit depth for temporal denoising. Output of spatial denoise. */
TextureFromPool hit_depth_tx_ = {"hit_depth_tx_"};
/** Ray hit variance for temporal denoising. Output of spatial denoise. */
TextureFromPool hit_variance_tx_ = {"hit_variance_tx_"};
/** Temporally stable variance for temporal denoising. Output of temporal denoise. */
TextureFromPool denoise_variance_tx_ = {"denoise_variance_tx_"};
/** Persistent texture reference for temporal denoising input. */
GPUTexture *radiance_history_tx_ = nullptr;
GPUTexture *variance_history_tx_ = nullptr;
GPUTexture *tilemask_history_tx_ = nullptr;
/** Radiance input for screen space tracing. */
GPUTexture *screen_radiance_front_tx_ = nullptr;
GPUTexture *screen_radiance_back_tx_ = nullptr;
Texture radiance_dummy_black_tx_ = {"radiance_dummy_black_tx"};
/** Dummy texture when the tracing is disabled. */
TextureFromPool dummy_result_tx_ = {"dummy_result_tx"};
/** Pointer to `inst_.render_buffers.depth_tx` updated before submission. */
GPUTexture *renderbuf_depth_view_ = nullptr;
/** Copy of the scene options to avoid changing parameters during motion blur. */
RaytraceEEVEE ray_tracing_options_;
int fast_gi_ray_count_ = 0;
int fast_gi_step_count_ = 0;
bool fast_gi_ao_only_ = 0;
RaytraceEEVEE_Method tracing_method_ = RAYTRACE_EEVEE_METHOD_PROBE;
RayTraceData &data_;
public:
RayTraceModule(Instance &inst, RayTraceData &data) : inst_(inst), data_(data){};
void init();
void sync();
/**
* RayTrace the scene and resolve radiance buffer for the corresponding `closure_bit`.
*
* IMPORTANT: Should not be conditionally executed as it manages the RayTraceResult.
* IMPORTANT: The screen tracing will be using the front and back Hierarchical-Z Buffer in its
* current state.
*
* \arg rt_buffer is the layer's permanent storage.
* \arg screen_radiance_back_tx is the texture used for screen space transmission rays.
* \arg screen_radiance_front_tx is the texture used for screen space reflection rays.
* \arg screen_radiance_persmat is the view projection matrix used for screen_radiance_front_tx.
* \arg active_closures is a mask of all active closures in a deferred layer.
* \arg main_view is the un-jittered view.
* \arg render_view is the TAA jittered view.
* \arg force_no_tracing will run the pipeline without any tracing, relying only on local probes.
*/
RayTraceResult render(RayTraceBuffer &rt_buffer,
GPUTexture *screen_radiance_back_tx,
eClosureBits active_closures,
/* TODO(fclem): Maybe wrap these two in some other class. */
View &main_view,
View &render_view);
/**
* Only allocate the RayTraceResult results buffers to be used by other passes.
*/
RayTraceResult alloc_only(RayTraceBuffer &rt_buffer);
/**
* Only allocate the RayTraceResult results buffers as dummy texture to ensure correct bindings.
*/
RayTraceResult alloc_dummy(RayTraceBuffer &rt_buffer);
void debug_pass_sync();
void debug_draw(View &view, GPUFrameBuffer *view_fb);
private:
RayTraceResultTexture trace(int closure_index,
bool active_layer,
RaytraceEEVEE options,
RayTraceBuffer &rt_buffer,
/* TODO(fclem): Maybe wrap these two in some other class. */
View &main_view,
View &render_view);
};
/** \} */
} // namespace blender::eevee