Merge branch 'blender-v4.1-release'

This commit is contained in:
Hans Goudey
2024-02-07 08:19:18 -05:00
7 changed files with 200 additions and 91 deletions

View File

@@ -149,9 +149,55 @@ OIDNFilter OIDNDenoiserGPU::create_filter()
denoiser_device_->set_error(error_message);
}
}
# if OIDN_VERSION_MAJOR >= 2
switch (quality_) {
case DENOISER_QUALITY_BALANCED:
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_BALANCED);
break;
case DENOISER_QUALITY_HIGH:
default:
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_HIGH);
}
# endif
return filter;
}
bool OIDNDenoiserGPU::commit_and_execute_filter(OIDNFilter filter, ExecMode mode)
{
const char *error_message = nullptr;
OIDNError err = OIDN_ERROR_NONE;
for (;;) {
oidnCommitFilter(filter);
if (mode == ExecMode::ASYNC) {
oidnExecuteFilterAsync(filter);
}
else {
oidnExecuteFilter(filter);
}
/* If OIDN runs out of memory, reduce mem limit and retry */
err = oidnGetDeviceError(oidn_device_, (const char **)&error_message);
if (err != OIDN_ERROR_OUT_OF_MEMORY || max_mem_ < 200) {
break;
}
max_mem_ = max_mem_ / 2;
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
}
if (err != OIDN_ERROR_NONE) {
if (error_message == nullptr) {
error_message = "Unspecified OIDN error";
}
LOG(ERROR) << "OIDN error: " << error_message;
denoiser_device_->set_error(error_message);
return false;
}
return true;
}
bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
{
const bool recreate_denoiser = (oidn_device_ == nullptr) || (oidn_filter_ == nullptr) ||
@@ -224,24 +270,8 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
oidnSetFilterBool(oidn_filter_, "hdr", true);
oidnSetFilterBool(oidn_filter_, "srgb", false);
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
if (params_.prefilter == DENOISER_PREFILTER_NONE ||
params_.prefilter == DENOISER_PREFILTER_ACCURATE)
{
oidnSetFilterInt(oidn_filter_, "cleanAux", true);
}
# if OIDN_VERSION_MAJOR >= 2
switch (params_.quality) {
case DENOISER_QUALITY_BALANCED:
oidnSetFilterInt(oidn_filter_, "quality", OIDN_QUALITY_BALANCED);
break;
case DENOISER_QUALITY_HIGH:
default:
oidnSetFilterInt(oidn_filter_, "quality", OIDN_QUALITY_HIGH);
}
quality_ = params_.quality;
# endif
if (context.use_pass_albedo) {
albedo_filter_ = create_filter();
@@ -295,6 +325,7 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
pass.denoised_offset * sizeof(float),
pass_stride_in_bytes,
pass_stride_in_bytes * context.buffer_params.stride);
set_filter_pass(oidn_filter_,
"output",
context.render_buffers->buffer.device_pointer,
@@ -312,8 +343,18 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
const int64_t row_stride_in_bytes = context.guiding_params.stride * pixel_stride_in_bytes;
if (context.use_pass_albedo) {
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
set_filter_pass(oidn_filter_,
set_filter_pass(oidn_filter_,
"albedo",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
set_filter_pass(albedo_filter_,
"albedo",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
@@ -322,17 +363,7 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
}
else {
set_filter_pass(albedo_filter_,
"color",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
set_filter_pass(albedo_filter_,
"output",
d_guiding_buffer,
@@ -342,36 +373,27 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnCommitFilter(albedo_filter_);
oidnExecuteFilterAsync(albedo_filter_);
set_filter_pass(oidn_filter_,
"albedo",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (!commit_and_execute_filter(albedo_filter_, ExecMode::ASYNC)) {
return false;
}
}
}
if (context.use_pass_normal) {
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
set_filter_pass(oidn_filter_,
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
}
else {
set_filter_pass(oidn_filter_,
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
set_filter_pass(normal_filter_,
"color",
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
@@ -390,47 +412,15 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnCommitFilter(normal_filter_);
oidnExecuteFilterAsync(normal_filter_);
set_filter_pass(oidn_filter_,
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (!commit_and_execute_filter(normal_filter_, ExecMode::ASYNC)) {
return false;
}
}
}
}
oidnCommitFilter(oidn_filter_);
oidnExecuteFilter(oidn_filter_);
const char *out_message = nullptr;
OIDNError err = oidnGetDeviceError(oidn_device_, (const char **)&out_message);
if (OIDN_ERROR_NONE != err) {
/* If OIDN runs out of memory, reduce mem limit and retry */
while (err == OIDN_ERROR_OUT_OF_MEMORY && max_mem_ > 200) {
max_mem_ = max_mem_ / 2;
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
oidnCommitFilter(oidn_filter_);
oidnExecuteFilter(oidn_filter_);
err = oidnGetDeviceError(oidn_device_, &out_message);
}
if (out_message) {
LOG(ERROR) << "OIDN error: " << out_message;
denoiser_device_->set_error(out_message);
}
else {
LOG(ERROR) << "OIDN error: unspecified";
denoiser_device_->set_error("Unspecified OIDN error");
}
return false;
}
return true;
oidnSetFilterInt(oidn_filter_, "cleanAux", params_.prefilter != DENOISER_PREFILTER_FAST);
return commit_and_execute_filter(oidn_filter_);
}
void OIDNDenoiserGPU::set_filter_pass(OIDNFilter filter,

View File

@@ -36,6 +36,11 @@ class OIDNDenoiserGPU : public DenoiserGPU {
static bool is_device_supported(const DeviceInfo &device);
protected:
enum class ExecMode {
SYNC,
ASYNC,
};
virtual uint get_device_type_mask() const override;
/* Create OIDN denoiser descriptor if needed.
@@ -50,6 +55,7 @@ class OIDNDenoiserGPU : public DenoiserGPU {
virtual bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) override;
OIDNFilter create_filter();
bool commit_and_execute_filter(OIDNFilter filter, ExecMode mode = ExecMode::SYNC);
void set_filter_pass(OIDNFilter filter,
const char *name,
@@ -73,7 +79,8 @@ class OIDNDenoiserGPU : public DenoiserGPU {
bool use_pass_normal_ = false;
DenoiserQuality quality_ = DENOISER_QUALITY_HIGH;
int max_mem_ = 3000;
/* Filter memory usage limit if we ran out of memory with OIDN's default limit. */
int max_mem_ = 768;
};
CCL_NAMESPACE_END

View File

@@ -4466,6 +4466,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
col.operator("mesh.set_sharpness_by_angle")
if with_freestyle:
col.separator()

View File

@@ -49,6 +49,7 @@ set(SRC
editmesh_rip_edge.cc
editmesh_select.cc
editmesh_select_similar.cc
editmesh_set_sharpness_by_angle.cc
editmesh_tools.cc
editmesh_undo.cc
editmesh_utils.cc

View File

@@ -0,0 +1,105 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edmesh
*/
#include "BLI_math_angle_types.hh"
#include "BLI_math_vector.hh"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.hh"
#include "BKE_editmesh.hh"
#include "BKE_layer.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "DEG_depsgraph.hh"
#include "WM_api.hh"
#include "ED_mesh.hh"
#include "ED_screen.hh"
#include "mesh_intern.hh"
namespace blender::ed::mesh {
static int set_sharpness_by_angle_exec(bContext *C, wmOperator *op)
{
const float angle_limit_cos = std::cos(RNA_float_get(op->ptr, "angle"));
const bool extend = RNA_boolean_get(op->ptr, "extend");
const Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_view3d(C));
for (Object *object : objects) {
Mesh &mesh = *static_cast<Mesh *>(object->data);
BMEditMesh *em = mesh.edit_mesh;
bool changed = false;
BMIter iter;
BMEdge *e;
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
continue;
}
const bool prev_sharp = !BM_elem_flag_test(e, BM_ELEM_SMOOTH);
if (extend && prev_sharp) {
continue;
}
BMLoop *l1, *l2;
if (!BM_edge_loop_pair(e, &l1, &l2)) {
continue;
}
const float angle_cos = math::dot(float3(l1->f->no), float3(l2->f->no));
const bool sharp = angle_cos <= angle_limit_cos;
BM_elem_flag_set(e, BM_ELEM_SMOOTH, !sharp);
changed = changed || sharp != prev_sharp;
}
if (changed) {
BKE_editmesh_lnorspace_update(em);
DEG_id_tag_update(&mesh.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &mesh.id);
}
}
return OPERATOR_FINISHED;
}
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot)
{
ot->name = "Set Sharpness by Angle";
ot->description = "Set edge sharpness based on the angle between neighboring faces";
ot->idname = "MESH_OT_set_sharpness_by_angle";
ot->exec = set_sharpness_by_angle_exec;
ot->poll = ED_operator_editmesh;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop = RNA_def_float_rotation(ot->srna,
"angle",
0,
nullptr,
math::AngleRadian::from_degree(0.01f).radian(),
math::AngleRadian::from_degree(180.0f).radian(),
"Angle",
"",
math::AngleRadian::from_degree(1.0f).radian(),
math::AngleRadian::from_degree(180.0f).radian());
RNA_def_property_float_default(prop, math::AngleRadian::from_degree(30.0f).radian());
RNA_def_boolean(ot->srna,
"extend",
false,
"Extend",
"Add new sharp edges without clearing existing sharp edges");
}
} // namespace blender::ed::mesh

View File

@@ -256,6 +256,9 @@ void MESH_OT_delete_loose(wmOperatorType *ot);
void MESH_OT_edge_collapse(wmOperatorType *ot);
void MESH_OT_faces_shade_smooth(wmOperatorType *ot);
void MESH_OT_faces_shade_flat(wmOperatorType *ot);
namespace blender::ed::mesh {
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot);
}
void MESH_OT_split(wmOperatorType *ot);
void MESH_OT_edge_rotate(wmOperatorType *ot);
void MESH_OT_hide(wmOperatorType *ot);

View File

@@ -22,6 +22,7 @@
void ED_operatortypes_mesh()
{
using namespace blender::ed::mesh;
WM_operatortype_append(MESH_OT_select_all);
WM_operatortype_append(MESH_OT_select_interior_faces);
WM_operatortype_append(MESH_OT_select_more);
@@ -98,6 +99,7 @@ void ED_operatortypes_mesh()
WM_operatortype_append(MESH_OT_delete_edgeloop);
WM_operatortype_append(MESH_OT_faces_shade_smooth);
WM_operatortype_append(MESH_OT_faces_shade_flat);
WM_operatortype_append(MESH_OT_set_sharpness_by_angle);
WM_operatortype_append(MESH_OT_sort_elements);
#ifdef WITH_FREESTYLE
WM_operatortype_append(MESH_OT_mark_freestyle_face);