EEVEE: Make sampling.reset() and sampling.is_reset() viewport only

This commit ensures correct usage of these functions.
Usage of them was not guarded and caused issues in render.

Fix #131804
This commit is contained in:
Clément Foucault
2024-12-12 18:36:52 +01:00
parent f160bc0806
commit afb0d41107
8 changed files with 57 additions and 43 deletions

View File

@@ -598,7 +598,7 @@ void Film::end_sync()
use_reprojection_ = inst_.sampling.interactive_mode();
/* Just bypass the reprojection and reset the accumulation. */
if (!use_reprojection_ && inst_.sampling.is_reset()) {
if (inst_.is_viewport() && !use_reprojection_ && inst_.sampling.is_reset()) {
use_reprojection_ = false;
data_.use_history = false;
}

View File

@@ -72,27 +72,29 @@ void Instance::init(const int2 &output_res,
return;
}
if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
sampling.reset();
}
if (output_res != film.display_extent_get()) {
sampling.reset();
}
if (output_rect) {
int2 offset = int2(output_rect->xmin, output_rect->ymin);
int2 extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect));
if (offset != film.get_data().offset || extent != film.get_data().extent) {
if (is_viewport()) {
if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
sampling.reset();
}
if (output_res != film.display_extent_get()) {
sampling.reset();
}
if (output_rect) {
int2 offset = int2(output_rect->xmin, output_rect->ymin);
int2 extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect));
if (offset != film.get_data().offset || extent != film.get_data().extent) {
sampling.reset();
}
}
if (assign_if_different(overlays_enabled_, v3d && !(v3d->flag2 & V3D_HIDE_OVERLAYS))) {
sampling.reset();
}
if (is_painting()) {
sampling.reset();
}
if (is_navigating() && scene->eevee.flag & SCE_EEVEE_SHADOW_JITTERED_VIEWPORT) {
sampling.reset();
}
}
if (assign_if_different(overlays_enabled_, v3d && !(v3d->flag2 & V3D_HIDE_OVERLAYS))) {
sampling.reset();
}
if (is_painting()) {
sampling.reset();
}
if (is_navigating() && scene->eevee.flag & SCE_EEVEE_SHADOW_JITTERED_VIEWPORT) {
sampling.reset();
}
sampling.init(scene);
@@ -175,7 +177,9 @@ void Instance::update_eval_members()
void Instance::view_update()
{
sampling.reset();
if (is_viewport()) {
sampling.reset();
}
}
/** \} */

View File

@@ -150,17 +150,19 @@ void SphereProbeModule::end_sync()
}
}
/* When reflection probes are synced the sampling must be reset.
*
* This fixes issues when using a single non-projected sample. Without resetting the
* previous rendered viewport will be drawn and reflection probes will not be updated.
* #Instance::render_sample */
if (instance_.do_lightprobe_sphere_sync()) {
instance_.sampling.reset();
}
/* If we cannot render probes this redraw make sure we request another redraw. */
if (update_probes_next_sample_ && (instance_.do_lightprobe_sphere_sync() == false)) {
DRW_viewport_request_redraw();
if (instance_.is_viewport()) {
/* When reflection probes are synced the sampling must be reset.
*
* This fixes issues when using a single non-projected sample. Without resetting the
* previous rendered viewport will be drawn and reflection probes will not be updated.
* #Instance::render_sample */
if (instance_.do_lightprobe_sphere_sync()) {
instance_.sampling.reset();
}
/* If we cannot render probes this redraw make sure we request another redraw. */
if (update_probes_next_sample_ && (instance_.do_lightprobe_sphere_sync() == false)) {
DRW_viewport_request_redraw();
}
}
}

View File

@@ -183,7 +183,7 @@ void LookdevModule::sync()
for (int index : IndexRange(num_spheres)) {
if (spheres_[index].color_tx_.ensure_2d(color_format, extent)) {
/* Request redraw if the light-probe were off and the sampling was already finished. */
if (inst_.sampling.finished_viewport()) {
if (inst_.is_viewport() && inst_.sampling.finished_viewport()) {
inst_.sampling.reset();
}
}

View File

@@ -210,7 +210,9 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
const bool is_transparent = GPU_material_flag_get(matpass.gpumat, GPU_MATFLAG_TRANSPARENT);
if (use_deferred_compilation && GPU_material_recalc_flag_get(matpass.gpumat)) {
if (inst_.is_viewport() && use_deferred_compilation &&
GPU_material_recalc_flag_get(matpass.gpumat))
{
/* TODO(Miguel Pozo): This is broken, it consumes the flag,
* but GPUMats can be shared across viewports. */
inst_.sampling.reset();

View File

@@ -236,6 +236,18 @@ void Sampling::step()
reset_ = false;
}
void Sampling::reset()
{
BLI_assert(inst_.is_viewport());
reset_ = true;
}
bool Sampling::is_reset() const
{
BLI_assert(inst_.is_viewport());
return reset_;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -78,16 +78,10 @@ class Sampling {
/* Viewport Only: Function to call to notify something in the scene changed.
* This will reset accumulation. Do not call after end_sync() or during sample rendering. */
void reset()
{
reset_ = true;
}
void reset();
/* Viewport Only: true if an update happened in the scene and accumulation needs reset. */
bool is_reset() const
{
return reset_;
}
bool is_reset() const;
template<typename PassType> void bind_resources(PassType &pass)
{

View File

@@ -348,7 +348,7 @@ void VolumeModule::draw_prepass(View &main_view)
* artifacts on lights because of voxels stretched in Z or anisotropy. */
exponential_frame_count = 8;
}
else if (inst_.sampling.is_reset()) {
else if (inst_.is_viewport() && inst_.sampling.is_reset()) {
/* If we are not falling in any cases above, this usually means there is a scene or object
* parameter update. Reset accumulation completely. */
exponential_frame_count = 0;