Fix T93727: Tiled render error in Cycles after changing temp directory

Consider temporary directory to be variant part of session configuration
which gets communicated to the tile manager on render reset.

This allows to be able to render with one temp directory, change the
directory, render again and have proper render result even with enabled
persistent data.

For the ease of access to the temp directory expose it via the render
engine API (engine.temp_directory).

Differential Revision: https://developer.blender.org/D13790
This commit is contained in:
Sergey Sharybin 2022-01-10 16:05:17 +01:00
parent 20cb2c72a5
commit 292c2cefe3
Notes: blender-bot 2023-02-13 22:37:44 +01:00
Referenced by issue #93727, Changing temporary directory results in errors with tiles while rendering in Cycles
10 changed files with 52 additions and 23 deletions

View File

@ -60,9 +60,8 @@ def init():
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
temp_path = bpy.app.tempdir
_cycles.init(path, user_path, temp_path, bpy.app.background)
_cycles.init(path, user_path, bpy.app.background)
_parse_command_line()

View File

@ -138,20 +138,18 @@ static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
{
PyObject *path, *user_path, *temp_path;
PyObject *path, *user_path;
int headless;
if (!PyArg_ParseTuple(args, "OOOi", &path, &user_path, &temp_path, &headless)) {
if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
return nullptr;
}
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr, *temp_path_coerce = nullptr;
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
path_init(PyC_UnicodeAsByte(path, &path_coerce),
PyC_UnicodeAsByte(user_path, &user_path_coerce),
PyC_UnicodeAsByte(temp_path, &temp_path_coerce));
PyC_UnicodeAsByte(user_path, &user_path_coerce));
Py_XDECREF(path_coerce);
Py_XDECREF(user_path_coerce);
Py_XDECREF(temp_path_coerce);
BlenderSession::headless = headless;

View File

@ -832,6 +832,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
SessionParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
if (background && !b_engine.is_preview()) {
/* Viewport and preview renders do not require temp directory and do request session
* parameters more often than the background render.
* Optimize RNA-C++ usage and memory allocation a bit by saving string access which we know is
* not needed for viewport render. */
params.temp_dir = b_engine.temporary_directory();
}
/* feature set */
params.experimental = (get_enum(cscene, "feature_set") != 0);

View File

@ -426,6 +426,11 @@ void Session::do_delayed_reset()
buffer_params_.update_passes(scene->passes);
tile_manager_.update(buffer_params_, scene);
/* Update temp directory on reset.
* This potentially allows to finish the existing rendering with a previously configure temporary
* direcotry in the host software and switch to a new temp directory when new render starts. */
tile_manager_.set_temp_dir(params.temp_dir);
/* Progress. */
progress.reset_sample();
progress.set_total_pixel_samples(static_cast<uint64_t>(buffer_params_.width) *

View File

@ -69,6 +69,9 @@ class SessionParams {
ShadingSystem shadingsystem;
/* Session-specific temporary directory to store in-progress EXR files in. */
string temp_dir;
SessionParams()
{
headless = false;

View File

@ -23,6 +23,7 @@
#include "scene/film.h"
#include "scene/integrator.h"
#include "scene/scene.h"
#include "session/session.h"
#include "util/algorithm.h"
#include "util/foreach.h"
#include "util/log.h"
@ -394,6 +395,11 @@ void TileManager::update(const BufferParams &params, const Scene *scene)
}
}
void TileManager::set_temp_dir(const string &temp_dir)
{
temp_dir_ = temp_dir;
}
bool TileManager::done()
{
return tile_state_.next_tile_index == tile_state_.num_tiles;
@ -452,7 +458,8 @@ const int2 TileManager::get_size() const
bool TileManager::open_tile_output()
{
write_state_.filename = path_temp_get("cycles-tile-buffer-" + tile_file_unique_part_ + "-" +
write_state_.filename = path_join(temp_dir_,
"cycles-tile-buffer-" + tile_file_unique_part_ + "-" +
to_string(write_state_.tile_file_index) + ".exr");
write_state_.tile_out = ImageOutput::create(write_state_.filename);

View File

@ -71,6 +71,8 @@ class TileManager {
* Will store all parameters needed for buffers access outside of the scene graph. */
void update(const BufferParams &params, const Scene *scene);
void set_temp_dir(const string &temp_dir);
inline int get_num_tiles() const
{
return tile_state_.num_tiles;
@ -136,6 +138,8 @@ class TileManager {
bool open_tile_output();
bool close_tile_output();
string temp_dir_;
/* Part of an on-disk tile file name which avoids conflicts between several Cycles instances or
* several sessions. */
string tile_file_unique_part_;

View File

@ -66,7 +66,6 @@ typedef struct stat path_stat_t;
static string cached_path = "";
static string cached_user_path = "";
static string cached_temp_path = "";
static string cached_xdg_cache_path = "";
namespace {
@ -336,11 +335,10 @@ static string path_xdg_cache_get()
}
#endif
void path_init(const string &path, const string &user_path, const string &temp_path)
void path_init(const string &path, const string &user_path)
{
cached_path = path;
cached_user_path = user_path;
cached_temp_path = temp_path;
#ifdef _MSC_VER
// workaround for https://svn.boost.org/trac/boost/ticket/6320
@ -384,15 +382,6 @@ string path_cache_get(const string &sub)
#endif
}
string path_temp_get(const string &sub)
{
if (cached_temp_path == "") {
cached_temp_path = Filesystem::temp_directory_path();
}
return path_join(cached_temp_path, sub);
}
#if defined(__linux__) || defined(__APPLE__)
string path_xdg_home_get(const string &sub = "");
#endif

View File

@ -32,10 +32,9 @@
CCL_NAMESPACE_BEGIN
/* program paths */
void path_init(const string &path = "", const string &user_path = "", const string &tmp_path = "");
void path_init(const string &path = "", const string &user_path = "");
string path_get(const string &sub = "");
string path_user_get(const string &sub = "");
string path_temp_get(const string &sub = "");
string path_cache_get(const string &sub = "");
/* path string manipulation */

View File

@ -98,6 +98,7 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = {
# include "RNA_access.h"
# include "BKE_appdir.h"
# include "BKE_context.h"
# include "BKE_report.h"
@ -420,6 +421,16 @@ static StructRNA *rna_RenderEngine_refine(PointerRNA *ptr)
&RNA_RenderEngine;
}
static void rna_RenderEngine_tempdir_get(PointerRNA * /*ptr*/, char *value)
{
BLI_strncpy(value, BKE_tempdir_session(), FILE_MAX);
}
static int rna_RenderEngine_tempdir_length(PointerRNA * /*ptr*/)
{
return strlen(BKE_tempdir_session());
}
static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr)
{
RenderEngine *engine = (RenderEngine *)ptr->data;
@ -860,6 +871,12 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "resolution_y");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "temporary_directory", PROP_STRING, PROP_NONE);
RNA_def_function_ui_description(func, "The temp directory used by Blender");
RNA_def_property_string_funcs(
prop, "rna_RenderEngine_tempdir_get", "rna_RenderEngine_tempdir_length", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
/* Render Data */
prop = RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "RenderSettings");