Caching generated image leads to infinite loop in preview render #53

Merged
Bogdan Nagirniak merged 12 commits from BLEN-409 into hydra-render 2023-06-13 18:39:39 +02:00
4 changed files with 42 additions and 32 deletions

View File

@ -16,6 +16,7 @@
#include "final_engine.h" #include "final_engine.h"
#include "preview_engine.h" #include "preview_engine.h"
#include "scene_delegate/image.h"
#include "viewport_engine.h" #include "viewport_engine.h"
namespace blender::render::hydra { namespace blender::render::hydra {
@ -221,6 +222,20 @@ static PyObject *engine_set_render_setting_func(PyObject * /*self*/, PyObject *a
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *cache_or_get_image_file_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pycontext, *pyimage;
if (!PyArg_ParseTuple(args, "OO", &pycontext, &pyimage)) {
Py_RETURN_NONE;
}
bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext);
Image *image = (Image *)PyLong_AsVoidPtr(pyimage);
std::string image_path = cache_or_get_image_file(image, context, nullptr);
return PyUnicode_FromString(image_path.c_str());
}
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
{"register_plugins", register_plugins_func, METH_VARARGS, ""}, {"register_plugins", register_plugins_func, METH_VARARGS, ""},
@ -233,6 +248,8 @@ static PyMethodDef methods[] = {
{"engine_set_sync_setting", engine_set_sync_setting_func, METH_VARARGS, ""}, {"engine_set_sync_setting", engine_set_sync_setting_func, METH_VARARGS, ""},
{"engine_set_render_setting", engine_set_render_setting_func, METH_VARARGS, ""}, {"engine_set_render_setting", engine_set_render_setting_func, METH_VARARGS, ""},
{"cache_or_get_image_file", cache_or_get_image_file_func, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}, {NULL, NULL, 0, NULL},
}; };

View File

@ -4,39 +4,38 @@
#include <pxr/imaging/hio/imageRegistry.h> #include <pxr/imaging/hio/imageRegistry.h>
#include "BKE_appdir.h" #include "BKE_appdir.h"
#include "BKE_image.h" #include "BKE_image_format.h"
#include "BKE_image_save.h" #include "BKE_image_save.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "DNA_windowmanager_types.h"
#include "blender_scene_delegate.h" #include "blender_scene_delegate.h"
#include "image.h" #include "image.h"
namespace blender::render::hydra { namespace blender::render::hydra {
static std::string cache_image_file(Image *image, static std::string cache_image_file(Image *image,
BlenderSceneDelegate *scene_delegate, bContext *context,
ImageUser *iuser, ImageUser *iuser,
bool check_exist) bool check_exist)
{ {
char file_path[FILE_MAX]; char file_path[FILE_MAX];
Main *main = CTX_data_main(context);
Scene *scene = CTX_data_scene(context);
ImageSaveOptions opts;
if (BKE_image_save_options_init(&opts, main, scene, image, iuser, false, false)) {
char file_name[32]; char file_name[32];
snprintf(file_name, sizeof(file_name), "img_%016llx.hdr", (uintptr_t)image); const char *r_ext;
BKE_image_path_ext_from_imformat(&scene->r.im_format, &r_ext);
snprintf(file_name, sizeof(file_name), "img_%016llx%s", (uintptr_t)image, r_ext);
BLI_path_join( BLI_path_join(
file_path, sizeof(file_path), BKE_tempdir_session(), "hydra_image_cache", file_name); file_path, sizeof(file_path), BKE_tempdir_session(), "hydra_image_cache", file_name);
if (check_exist && BLI_exists(file_path)) { if (check_exist && BLI_exists(file_path)) {
return file_path; return file_path;
} }
opts.save_copy = true;
Main *main = CTX_data_main(scene_delegate->context);
ImageSaveOptions opts;
opts.im_format.imtype = R_IMF_IMTYPE_RADHDR;
if (BKE_image_save_options_init(&opts, main, scene_delegate->scene, image, iuser, false, false))
{
STRNCPY(opts.filepath, file_path); STRNCPY(opts.filepath, file_path);
if (BKE_image_save(nullptr, main, image, iuser, &opts)) { if (BKE_image_save(nullptr, main, image, iuser, &opts)) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s -> %s", image->id.name, file_path); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s -> %s", image->id.name, file_path);
@ -47,27 +46,24 @@ static std::string cache_image_file(Image *image,
} }
BKE_image_save_options_free(&opts); BKE_image_save_options_free(&opts);
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s -> %s", image->id.name, file_path);
return file_path; return file_path;
} }
std::string cache_or_get_image_file(Image *image, std::string cache_or_get_image_file(Image *image, bContext *context, ImageUser *iuser)
BlenderSceneDelegate *scene_delegate,
ImageUser *iuser)
{ {
std::string file_path(FILE_MAX, 0); std::string file_path(FILE_MAX, 0);
if (image->source == IMA_SRC_GENERATED) { if (image->source == IMA_SRC_GENERATED) {
file_path = cache_image_file(image, scene_delegate, iuser, false); file_path = cache_image_file(image, context, iuser, false);
} }
else if (BKE_image_has_packedfile(image)) { else if (BKE_image_has_packedfile(image)) {
file_path = cache_image_file(image, scene_delegate, iuser, true); file_path = cache_image_file(image, context, iuser, true);
} }
else { else {
Main *main = CTX_data_main(scene_delegate->context); Main *main = CTX_data_main(context);
BKE_image_user_file_path_ex(main, iuser, image, file_path.data(), false, true); BKE_image_user_file_path_ex(main, iuser, image, file_path.data(), false, true);
if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(file_path)) { if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(file_path)) {
file_path = cache_image_file(image, scene_delegate, iuser, true); file_path = cache_image_file(image, context, iuser, true);
} }
} }

View File

@ -3,15 +3,11 @@
#pragma once #pragma once
#include "BKE_context.h"
#include "BKE_image.h" #include "BKE_image.h"
#include "BKE_image_save.h"
namespace blender::render::hydra { namespace blender::render::hydra {
class BlenderSceneDelegate; std::string cache_or_get_image_file(Image *image, bContext *context, ImageUser *iuser);
std::string cache_or_get_image_file(Image *image,
BlenderSceneDelegate *scene_delegate,
ImageUser *iuser);
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -87,7 +87,8 @@ void WorldData::init()
NodeTexImage *tex = static_cast<NodeTexImage *>(color_input_node->storage); NodeTexImage *tex = static_cast<NodeTexImage *>(color_input_node->storage);
Image *image = (Image *)color_input_node->id; Image *image = (Image *)color_input_node->id;
if (image) { if (image) {
std::string image_path = cache_or_get_image_file(image, scene_delegate_, &tex->iuser); std::string image_path = cache_or_get_image_file(
image, scene_delegate_->context, &tex->iuser);
if (!image_path.empty()) { if (!image_path.empty()) {
data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path); data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path);
} }