BLEN-365: Improve creation algorithm of PreviewEngine #21

Merged
Bogdan Nagirniak merged 11 commits from BLEN-365 into hydra-render 2023-04-10 12:44:48 +02:00
8 changed files with 115 additions and 24 deletions

View File

@ -19,7 +19,7 @@ class CustomHydraRenderEngine(HydraRenderEngine):
def register(cls): def register(cls):
super().register() super().register()
bpy_hydra.register_plugins(["/path/to/plugin")], ["/additional/system/path")]) bpy_hydra.register_plugins(["/path/to/plugin")])
def get_delegate_settings(self, engine_type): def get_delegate_settings(self, engine_type):
return { return {
@ -59,6 +59,7 @@ class HydraRenderEngine(bpy.types.RenderEngine):
return return
_bpy_hydra.engine_free(self.engine_ptr) _bpy_hydra.engine_free(self.engine_ptr)
del self.engine_ptr
@classmethod @classmethod
def register(cls): def register(cls):
@ -75,16 +76,14 @@ class HydraRenderEngine(bpy.types.RenderEngine):
# final render # final render
def update(self, data, depsgraph): def update(self, data, depsgraph):
pass
def render(self, depsgraph):
engine_type = 'PREVIEW' if self.is_preview else 'FINAL' engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id) self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id)
delegate_settings = self.get_delegate_settings(engine_type) delegate_settings = self.get_delegate_settings(engine_type)
_bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings) _bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings)
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
def render(self, depsgraph):
if self.engine_ptr:
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
# viewport render # viewport render
def view_update(self, context, depsgraph): def view_update(self, context, depsgraph):

View File

@ -5,17 +5,64 @@
#include "camera.h" #include "camera.h"
#include "preview_engine.h" #include "preview_engine.h"
#include "BLI_timer.h"
namespace blender::render::hydra { namespace blender::render::hydra {
const double LIFETIME = 180.0;
std::unique_ptr<PreviewEngine> PreviewEngine::instance;
void PreviewEngine::schedule_free()
{
DagerD marked this conversation as resolved Outdated

Move this to clear()

Move this to clear()
instance->render_delegate->Stop();
/* Register timer for schedule free PreviewEngine instance */
BLI_timer_register((uintptr_t)instance.get(),
free_instance,
nullptr,
nullptr,
LIFETIME,
true);
}
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id)
{
if (!instance) {
instance = std::make_unique<PreviewEngine>(bl_engine, render_delegate_id);
}
if (BLI_timer_is_registered((uintptr_t)instance.get())) {
/* Unregister timer while PreviewEngine is working */
BLI_timer_unregister((uintptr_t)instance.get());
}
instance->update(bl_engine, render_delegate_id);
return instance.get();
}
double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
{
if (!instance->render_task_delegate->is_converged()) {
/* Restart timer if render isn't completed */
return LIFETIME;
}
CLOG_INFO(LOG_EN, 2, "");
instance = nullptr;
return -1;
}
void PreviewEngine::sync(Depsgraph *depsgraph, void PreviewEngine::sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) pxr::HdRenderSettingsMap &render_settings)
{ {
scene_delegate = std::make_unique<BlenderSceneDelegate>( if (!scene_delegate) {
render_index.get(), scene_delegate = std::make_unique<BlenderSceneDelegate>(
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"), render_index.get(),
BlenderSceneDelegate::EngineType::PREVIEW); pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::PREVIEW);
}
scene_delegate->clear();
scene_delegate->populate(depsgraph, context); scene_delegate->populate(depsgraph, context);
for (auto const &setting : render_settings) { for (auto const &setting : render_settings) {
@ -70,6 +117,12 @@ void PreviewEngine::render(Depsgraph *depsgraph)
update_render_result(layer_name, res[0], res[1], pixels); update_render_result(layer_name, res[0], res[1], pixels);
} }
void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_id)
{
this->bl_engine = bl_engine;
/* TODO: recreate render_delegate when render_delegate_id is changed */
}
void PreviewEngine::update_render_result(const std::string &layer_name, void PreviewEngine::update_render_result(const std::string &layer_name,
int width, int width,
int height, int height,

View File

@ -8,21 +8,28 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class PreviewEngine : public FinalEngine { class PreviewEngine : public FinalEngine {
private:
/* Singleton class instance */
static std::unique_ptr<PreviewEngine> instance;
static double free_instance(uintptr_t uuid, void *user_data);
public: public:
static PreviewEngine *get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id);
static void schedule_free();
using FinalEngine::FinalEngine; using FinalEngine::FinalEngine;
void sync(Depsgraph *depsgraph, void sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) override; pxr::HdRenderSettingsMap &render_settings) override;
void render(Depsgraph *depsgraph) override; void render(Depsgraph *depsgraph) override;
protected: private:
void update(RenderEngine *bl_engine, const std::string &render_delegate_id);
void update_render_result(const std::string &layer_name, void update_render_result(const std::string &layer_name,
int width, int width,
int height, int height,
std::vector<float> &pixels); std::vector<float> &pixels);
protected:
pxr::HdRenderSettingsMap render_settings;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -16,6 +16,8 @@
#include "utils.h" #include "utils.h"
#include "viewport_engine.h" #include "viewport_engine.h"
#include "BLI_timer.h"
namespace blender::render::hydra { namespace blender::render::hydra {
static PyObject *init_func(PyObject * /*self*/, PyObject *args) static PyObject *init_func(PyObject * /*self*/, PyObject *args)
DagerD marked this conversation as resolved Outdated

move to PreviewEngine class as static

move to PreviewEngine class as static
@ -112,7 +114,7 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
engine = new ViewportEngine(bl_engine, render_delegate_id); engine = new ViewportEngine(bl_engine, render_delegate_id);
} }
else if (STREQ(engine_type, "PREVIEW")) { else if (STREQ(engine_type, "PREVIEW")) {
engine = new PreviewEngine(bl_engine, render_delegate_id); engine = PreviewEngine::get_instance(bl_engine, render_delegate_id);
} }
else { else {
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) { if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
@ -136,7 +138,13 @@ static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
} }
DagerD marked this conversation as resolved Outdated

Add PreviewEngine::update_engine() instead public usage of bl_engine

Add PreviewEngine::update_engine() instead public usage of bl_engine
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine);
delete engine; PreviewEngine *preview_engine = dynamic_cast<PreviewEngine *>(engine);
if (preview_engine) {
PreviewEngine::schedule_free();
}
else {
delete engine;
}
CLOG_INFO(LOG_EN, 2, "Engine %016llx", engine); CLOG_INFO(LOG_EN, 2, "Engine %016llx", engine);
Py_RETURN_NONE; Py_RETURN_NONE;

View File

@ -434,4 +434,18 @@ pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
return pxr::VtValue(); return pxr::VtValue();
} }
void BlenderSceneDelegate::clear()
{
for (auto &it : materials) {
DagerD marked this conversation as resolved Outdated
for (auto &it : materials) {
  it.second->remove();
}
``` for (auto &it : materials) { it.second->remove(); } ```
it.second->remove();
}
for (auto &it : objects) {
it.second->remove();
}
materials.clear();
objects.clear();
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -33,6 +33,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
void populate(Depsgraph *depsgraph, bContext *context); void populate(Depsgraph *depsgraph, bContext *context);
void clear();
// delegate methods // delegate methods
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override; pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;

View File

@ -7,7 +7,6 @@
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
#include <pxr/usd/usdLux/tokens.h> #include <pxr/usd/usdLux/tokens.h>
#include "BKE_light.h"
#include "DNA_light_types.h" #include "DNA_light_types.h"
#include "blender_scene_delegate.h" #include "blender_scene_delegate.h"
@ -80,13 +79,14 @@ void LightData::init()
break; break;
} }
p_type = prim_type(light);
/* TODO: temporary value, it should be delivered through Python UI */ /* TODO: temporary value, it should be delivered through Python UI */
data[pxr::HdLightTokens->exposure] = 1.0f; data[pxr::HdLightTokens->exposure] = 1.0f;
} }
pxr::TfToken LightData::prim_type() pxr::TfToken LightData::prim_type(Light *light)
{ {
Light *light = (Light *)((Object *)id)->data;
pxr::TfToken ret; pxr::TfToken ret;
switch (light->type) { switch (light->type) {
case LA_LOCAL: case LA_LOCAL:
@ -155,21 +155,27 @@ bool LightData::update_visibility(View3D *view3d)
void LightData::insert() void LightData::insert()
{ {
CLOG_INFO(LOG_BSD, 2, "%s", id->name); CLOG_INFO(LOG_BSD, 2, "%s", id->name);
scene_delegate->GetRenderIndex().InsertSprim(prim_type(), scene_delegate, p_id); scene_delegate->GetRenderIndex().InsertSprim(p_type, scene_delegate, p_id);
} }
void LightData::remove() void LightData::remove()
{ {
CLOG_INFO(LOG_BSD, 2, "%s", id->name); CLOG_INFO(LOG_BSD, 2, "%s", id->name);
scene_delegate->GetRenderIndex().RemoveSprim(prim_type(), p_id); scene_delegate->GetRenderIndex().RemoveSprim(p_type, p_id);
} }
void LightData::update() void LightData::update()
{ {
/* TODO: prim_type was changed we have to do remove..add light */
CLOG_INFO(LOG_BSD, 2, "%s", id->name); CLOG_INFO(LOG_BSD, 2, "%s", id->name);
Light *light = (Light *)((Object *)id)->data;
if (prim_type(light) != p_type) {
remove();
init();
insert();
return;
}
pxr::HdDirtyBits bits = pxr::HdLight::Clean; pxr::HdDirtyBits bits = pxr::HdLight::Clean;
if (id->recalc & ID_RECALC_GEOMETRY) { if (id->recalc & ID_RECALC_GEOMETRY) {
init(); init();

View File

@ -7,6 +7,8 @@
#include <pxr/usd/sdf/assetPath.h> #include <pxr/usd/sdf/assetPath.h>
#include <pxr/usd/sdf/path.h> #include <pxr/usd/sdf/path.h>
#include "BKE_light.h"
#include "object.h" #include "object.h"
namespace blender::render::hydra { namespace blender::render::hydra {
@ -24,7 +26,8 @@ class LightData : public ObjectData {
private: private:
std::map<pxr::TfToken, pxr::VtValue> data; std::map<pxr::TfToken, pxr::VtValue> data;
DagerD marked this conversation as resolved Outdated

pxr::TfToken p_type;
make prim_type() with Light * parameter

`pxr::TfToken p_type;` make prim_type() with `Light *` parameter
pxr::TfToken prim_type(); pxr::TfToken p_type;
pxr::TfToken prim_type(Light *light);
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra