BLEN-333: Use DNA instead RNA blender API for export/update depsgraph #3

Merged
Bogdan Nagirniak merged 7 commits from BLEN-333 into hydra-render 2023-02-21 09:48:32 +01:00
12 changed files with 260 additions and 187 deletions

View File

@ -74,6 +74,8 @@ set(SRC
sceneDelegate/light.cc sceneDelegate/light.cc
sceneDelegate/world.h sceneDelegate/world.h
sceneDelegate/world.cc sceneDelegate/world.cc
sceneDelegate/instance.h
sceneDelegate/instance.cc
) )
set(LIB set(LIB

View File

@ -23,7 +23,7 @@ void FinalEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, pxr::
{ {
sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(), sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(),
SdfPath::AbsoluteRootPath().AppendElementString("scene")); SdfPath::AbsoluteRootPath().AppendElementString("scene"));
sceneDelegate->Populate(b_depsgraph, b_context); sceneDelegate->populate((Depsgraph *)b_depsgraph.ptr.data, (bContext *)b_context.ptr.data);
for (auto const& setting : renderSettings) { for (auto const& setting : renderSettings) {
renderDelegate->SetRenderSetting(setting.first, setting.second); renderDelegate->SetRenderSetting(setting.first, setting.second);

View File

@ -1,27 +1,22 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */ * Copyright 2011-2022 Blender Foundation */
#include <pxr/imaging/hd/light.h> #include "DEG_depsgraph_query.h"
#include <pxr/imaging/hd/material.h> #include "DNA_scene_types.h"
#include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/usd/usdLux/tokens.h>
#include <pxr/imaging/hdSt/tokens.h>
#include "glog/logging.h" #include "glog/logging.h"
#include "blenderSceneDelegate.h" #include "blenderSceneDelegate.h"
#include "object.h"
using namespace std; using namespace pxr;
namespace blender::render::hydra { namespace blender::render::hydra {
BlenderSceneDelegate::BlenderSceneDelegate(HdRenderIndex* parentIndex, SdfPath const& delegateID) BlenderSceneDelegate::BlenderSceneDelegate(HdRenderIndex* parentIndex, SdfPath const& delegateID)
: HdSceneDelegate(parentIndex, delegateID), : HdSceneDelegate(parentIndex, delegateID)
b_depsgraph(nullptr), , depsgraph(nullptr)
b_context(nullptr), , context(nullptr)
view3d(nullptr), , view3d(nullptr)
is_populated(false)
{ {
} }
@ -54,16 +49,17 @@ void BlenderSceneDelegate::update_material(Material *material)
void BlenderSceneDelegate::update_world() void BlenderSceneDelegate::update_world()
{ {
World *world = (World *)b_depsgraph->scene().world().ptr.data; Scene *scene = DEG_get_input_scene(depsgraph);
World *world = scene->world;
if (!world_data) { if (!world_data) {
if (world) { if (world) {
world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data); world_data = WorldData::init(this, world, context);
world_data->insert_prim(); world_data->insert_prim();
} }
} }
else { else {
if (world) { if (world) {
world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data); world_data = WorldData::init(this, world, context);
world_data->mark_prim_dirty(IdData::DirtyBits::AllDirty); world_data->mark_prim_dirty(IdData::DirtyBits::AllDirty);
} }
else { else {
@ -82,55 +78,80 @@ bool BlenderSceneDelegate::GetVisible(SdfPath const &id)
return object_data(id)->visible; return object_data(id)->visible;
} }
void BlenderSceneDelegate::update_collection() void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
{ {
/* add new objects */ if (visibility) {
std::set<SdfPath> available_objects; /* Check and update visibility */
for (auto &inst : b_depsgraph->object_instances) { for (auto &obj : objects) {
if (inst.is_instance()) { if (obj.second->update_visibility(view3d)) {
continue; obj.second->mark_prim_dirty(IdData::DirtyBits::DirtyVisibility);
};
} }
Object *object = (Object *)inst.object().ptr.data; }
if (!supported_object(object)) {
continue;
}
available_objects.insert(ObjectData::prim_id(this, object));
if (!is_populated) { /* Export of new visible objects which were not exported before */
std::set<SdfPath> available_objects;
DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_DUPLI;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
&data, Object *, object) {
if (data.dupli_object_current != nullptr) {
InstanceData i_data(this, data.dupli_object_current);
LOG(INFO) << "Instance: " << i_data.name() << " " << i_data.random_id();
continue;
}
if (!ObjectData::supported(object)) {
continue;
}
SdfPath id = ObjectData::prim_id(this, object);
if (remove) {
available_objects.insert(id);
}
if (!object_data(id)) {
add_update_object(object, true, true, true); add_update_object(object, true, true, true);
} }
} }
ITER_END;
if (!is_populated) { if (remove) {
return; /* remove unused objects */
} for (auto it = objects.begin(); it != objects.end(); ++it) {
if (available_objects.find(it->first) != available_objects.end()) {
continue;
}
it->second->remove_prim();
objects.erase(it);
it = objects.begin();
}
/* remove unused objects */ /* remove unused materials */
for (auto it = objects.begin(); it != objects.end(); ++it) { std::set<SdfPath> available_materials;
if (available_objects.find(it->first) != available_objects.end()) { for (auto &obj : objects) {
continue; MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
if (m_data && !m_data->material_id.IsEmpty()) {
available_materials.insert(m_data->material_id);
}
} }
it->second->remove_prim(); for (auto it = materials.begin(); it != materials.end(); ++it) {
objects.erase(it); if (available_materials.find(it->first) != available_materials.end()) {
it = objects.begin(); continue;
} }
it->second->remove_prim();
/* remove unused materials */ materials.erase(it);
std::set<SdfPath> available_materials; it = materials.begin();
for (auto &obj : objects) {
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
if (m_data && !m_data->material_id.IsEmpty()) {
available_materials.insert(m_data->material_id);
} }
} }
for (auto it = materials.begin(); it != materials.end(); ++it) {
if (available_materials.find(it->first) != available_materials.end()) {
continue;
}
it->second->remove_prim();
materials.erase(it);
it = materials.begin();
}
} }
void BlenderSceneDelegate::add_update_object(Object *object, bool geometry, bool transform, bool shading) void BlenderSceneDelegate::add_update_object(Object *object, bool geometry, bool transform, bool shading)
@ -198,31 +219,18 @@ MaterialData *BlenderSceneDelegate::material_data(SdfPath const &id)
return it->second.get(); return it->second.get();
} }
bool BlenderSceneDelegate::supported_object(Object *object) void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
{ {
return object->type == OB_MESH || bool is_populated = depsgraph != nullptr;
object->type == OB_LAMP ||
object->type == OB_SURF ||
object->type == OB_FONT ||
object->type == OB_CURVES ||
object->type == OB_CURVES_LEGACY ||
object->type == OB_MBALL;
}
void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont) depsgraph = deps;
{ context = cont;
LOG(INFO) << "Populate " << is_populated; view3d = CTX_wm_view3d(context);
b_depsgraph = &b_deps;
b_context = &b_cont;
view3d = (View3D *)b_context->space_data().ptr.data;
if (!is_populated) { if (!is_populated) {
/* Export initial objects */ /* Export initial objects */
update_collection(); update_collection(false, false);
update_world(); update_world();
is_populated = true;
return; return;
} }
@ -230,96 +238,75 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
bool do_update_collection = false; bool do_update_collection = false;
bool do_update_visibility = false; bool do_update_visibility = false;
bool do_update_world = false; bool do_update_world = false;
bool transform, geometry, shading;
for (auto &update : b_depsgraph->updates) { DEGIDIterData data = {0};
BL::ID id = update.id(); data.graph = depsgraph;
LOG(INFO) << "Update: " << id.name_full() << " [" data.only_updated = true;
<< update.is_updated_transform() ITER_BEGIN (DEG_iterator_ids_begin,
<< update.is_updated_geometry() DEG_iterator_ids_next,
<< update.is_updated_shading() << "]"; DEG_iterator_ids_end,
&data, ID *, id) {
if (id.is_a(&RNA_Object)) { transform = (id->recalc & ID_RECALC_TRANSFORM) != 0;
Object *object = (Object *)id.ptr.data; shading = (id->recalc & (ID_RECALC_SHADING | ID_RECALC_ANIMATION)) != 0;
if (!supported_object(object)) { geometry = (id->recalc & ID_RECALC_GEOMETRY) != 0;
continue;
}
add_update_object(object,
update.is_updated_geometry(),
update.is_updated_transform(),
update.is_updated_shading());
continue;
}
if (id.is_a(&RNA_Material)) { LOG(INFO) << "Update: " << id->name << " [" << transform << geometry << shading << "]";
if (update.is_updated_shading()) {
Material *material = (Material *)id.ptr.data;
update_material(material);
}
continue;
}
if (id.is_a(&RNA_Collection)) {
if (update.is_updated_transform() && update.is_updated_geometry()) {
do_update_collection = true;
}
continue;
}
if (id.is_a(&RNA_Scene)) { switch (GS(id->name)) {
if (!update.is_updated_geometry() && !update.is_updated_transform() && !update.is_updated_shading()) { case ID_OB: {
do_update_visibility = true; Object *object = (Object *)id;
if (!ObjectData::supported(object)) {
break;
}
geometry |= (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) != 0;
add_update_object(object, geometry, transform, shading);
}
break;
Scene *scene = (Scene *)id.ptr.data; case ID_MA:
if ((scene->world && !world_data) || (!scene->world && world_data)) { if (shading) {
Material *material = (Material *)id;
update_material(material);
}
break;
case ID_GR:
if (transform && geometry) {
do_update_collection = true;
}
break;
case ID_SCE:
if (!geometry && !transform && !shading) {
Scene *scene = (Scene *)id;
do_update_visibility = true;
if ((scene->world && !world_data) || (!scene->world && world_data)) {
do_update_world = true;
}
}
break;
case ID_WO:
if (shading) {
do_update_world = true; do_update_world = true;
} }
} break;
continue;
}
if (id.is_a(&RNA_World)) { default:
if (update.is_updated_shading()) { break;
do_update_world = true;
}
continue;
} }
} }
ITER_END;
if (do_update_collection) { if (do_update_collection || do_update_visibility) {
update_collection(); update_collection(do_update_collection, do_update_visibility);
}
if (do_update_visibility) {
update_visibility();
} }
if (do_update_world) { if (do_update_world) {
update_world(); update_world();
} }
}
void BlenderSceneDelegate::update_visibility()
{
/* Check and update visibility */
for (auto &obj : objects) {
if (obj.second->update_visibility(view3d)) {
obj.second->mark_prim_dirty(IdData::DirtyBits::DirtyVisibility);
};
}
/* Export of new visible objects which were not exported before */
for (auto &inst : b_depsgraph->object_instances) {
if (inst.is_instance()) {
continue;
}
Object *object = (Object *)inst.object().ptr.data;
if (!supported_object(object)) {
continue;
}
if (!object_data(ObjectData::prim_id(this, object))) {
add_update_object(object, true, true, true);
}
}
} }
HdMeshTopology BlenderSceneDelegate::GetMeshTopology(SdfPath const& id) HdMeshTopology BlenderSceneDelegate::GetMeshTopology(SdfPath const& id)

View File

@ -3,65 +3,57 @@
#pragma once #pragma once
#include <map>
#include <pxr/pxr.h>
#include <pxr/imaging/hd/camera.h>
#include <pxr/imaging/hd/sceneDelegate.h> #include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/imaging/hd/renderIndex.h>
#include <pxr/usd/usd/stage.h>
#include "MEM_guardedalloc.h" #include "BKE_context.h"
#include "RNA_blender_cpp.h" #include "DEG_depsgraph.h"
#include "object.h" #include "object.h"
#include "mesh.h" #include "mesh.h"
#include "light.h" #include "light.h"
#include "world.h" #include "world.h"
#include "instance.h"
using namespace pxr;
namespace blender::render::hydra { namespace blender::render::hydra {
class BlenderSceneDelegate : public HdSceneDelegate { class BlenderSceneDelegate : public pxr::HdSceneDelegate {
public: public:
BlenderSceneDelegate(HdRenderIndex* renderIndex, SdfPath const &delegateId); BlenderSceneDelegate(pxr::HdRenderIndex *renderIndex, pxr::SdfPath const &delegateId);
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
void Populate(BL::Depsgraph &b_deps, BL::Context &b_context); void populate(Depsgraph *depsgraph, bContext *context);
// delegate methods // delegate methods
HdMeshTopology GetMeshTopology(SdfPath const& id) override; pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
GfMatrix4d GetTransform(SdfPath const& id) override; pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override;
VtValue Get(SdfPath const& id, TfToken const& key) override; pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
VtValue GetLightParamValue(SdfPath const& id, TfToken const& key) override; pxr::VtValue GetLightParamValue(pxr::SdfPath const &id, pxr::TfToken const &key) override;
HdPrimvarDescriptorVector GetPrimvarDescriptors(SdfPath const& id, HdInterpolation interpolation) override; pxr::HdPrimvarDescriptorVector GetPrimvarDescriptors(pxr::SdfPath const &id, pxr::HdInterpolation interpolation) override;
SdfPath GetMaterialId(SdfPath const &rprimId) override; pxr::SdfPath GetMaterialId(pxr::SdfPath const &rprimId) override;
VtValue GetMaterialResource(SdfPath const &materialId) override; pxr::VtValue GetMaterialResource(pxr::SdfPath const &materialId) override;
bool GetVisible(SdfPath const &id) override; bool GetVisible(pxr::SdfPath const &id) override;
private: private:
ObjectData *object_data(SdfPath const &id); ObjectData *object_data(pxr::SdfPath const &id);
MeshData *mesh_data(SdfPath const &id); MeshData *mesh_data(pxr::SdfPath const &id);
LightData *light_data(SdfPath const &id); LightData *light_data(pxr::SdfPath const &id);
MaterialData *material_data(SdfPath const &id); MaterialData *material_data(pxr::SdfPath const &id);
bool supported_object(Object *object);
void add_update_object(Object *object, bool geometry, bool transform, bool shading); void add_update_object(Object *object, bool geometry, bool transform, bool shading);
void set_material(MeshData &mesh_data); void set_material(MeshData &mesh_data);
void update_material(Material *material); void update_material(Material *material);
void update_world(); void update_world();
void update_collection(); void update_collection(bool remove, bool visibility);
void update_visibility();
private: private:
BL::Depsgraph *b_depsgraph; Depsgraph *depsgraph;
BL::Context *b_context; bContext *context;
View3D *view3d; View3D *view3d;
bool is_populated;
ObjectDataMap objects; ObjectDataMap objects;
MaterialDataMap materials; MaterialDataMap materials;
std::unique_ptr<WorldData> world_data; std::unique_ptr<WorldData> world_data;
InstanceDataMap instances;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "instance.h"
using namespace pxr;
namespace blender::render::hydra {
InstanceData::InstanceData(pxr::HdSceneDelegate *scene_delegate, DupliObject *dupli)
: IdData(scene_delegate, (ID *)dupli->ob_data)
, dupli(dupli)
{
}
int InstanceData::random_id()
{
return dupli->random_id;
}
VtValue InstanceData::get_data(TfToken const &key)
{
return VtValue();
}
void InstanceData::insert_prim()
{
}
void InstanceData::remove_prim()
{
}
void InstanceData::mark_prim_dirty(DirtyBits dirty_bits)
{
}
} // namespace blender::render::hydra

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include "BKE_duplilist.h"
#include "id.h"
namespace blender::render::hydra {
class InstanceData: public IdData {
public:
InstanceData(pxr::HdSceneDelegate *scene_delegate, DupliObject *dupli);
int random_id();
pxr::VtValue get_data(pxr::TfToken const &key) override;
void insert_prim() override;
void remove_prim() override;
void mark_prim_dirty(DirtyBits dirty_bits) override;
public:
DupliObject *dupli;
};
using InstanceDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<InstanceData>, pxr::SdfPath::Hash>;
} // namespace blender::render::hydra

View File

@ -151,6 +151,8 @@ void LightData::remove_prim()
void LightData::mark_prim_dirty(DirtyBits dirty_bits) void LightData::mark_prim_dirty(DirtyBits dirty_bits)
{ {
/* TODO: prim_type was changed we have to do remove..add light */
HdDirtyBits bits = HdLight::Clean; HdDirtyBits bits = HdLight::Clean;
switch (dirty_bits) { switch (dirty_bits) {
case DirtyBits::DirtyTransform: case DirtyBits::DirtyTransform:

View File

@ -13,9 +13,6 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class MaterialData;
using MaterialDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<MaterialData>, pxr::SdfPath::Hash>;
class MaterialData: IdData { class MaterialData: IdData {
public: public:
static std::unique_ptr<MaterialData> init(pxr::HdSceneDelegate *scene_delegate, Material *material); static std::unique_ptr<MaterialData> init(pxr::HdSceneDelegate *scene_delegate, Material *material);
@ -35,4 +32,6 @@ private:
pxr::SdfAssetPath mtlx_path; pxr::SdfAssetPath mtlx_path;
}; };
using MaterialDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<MaterialData>, pxr::SdfPath::Hash>;
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -160,6 +160,14 @@ void MeshData::mark_prim_dirty(DirtyBits dirty_bits)
{ {
SdfPath p_id = prim_id(scene_delegate, (Object *)id); SdfPath p_id = prim_id(scene_delegate, (Object *)id);
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) { if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
/* Trying to insert prim */
insert_prim();
return;
}
if (face_vertex_counts.empty()) {
/* Remove prim without faces */
remove_prim();
return; return;
} }

View File

@ -12,6 +12,24 @@ using namespace pxr;
namespace blender::render::hydra { namespace blender::render::hydra {
bool ObjectData::supported(Object *object)
{
switch (object->type) {
case OB_MESH:
case OB_SURF:
case OB_FONT:
case OB_CURVES:
case OB_CURVES_LEGACY:
case OB_MBALL:
case OB_LAMP:
return true;
default:
break;
}
return false;
}
std::unique_ptr<ObjectData> ObjectData::init(pxr::HdSceneDelegate *scene_delegate, Object *object) std::unique_ptr<ObjectData> ObjectData::init(pxr::HdSceneDelegate *scene_delegate, Object *object)
{ {
switch (object->type) { switch (object->type) {

View File

@ -14,11 +14,9 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class ObjectData;
using ObjectDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<ObjectData>, pxr::SdfPath::Hash>;
class ObjectData: public IdData { class ObjectData: public IdData {
public: public:
static bool supported(Object *object);
static std::unique_ptr<ObjectData> init(pxr::HdSceneDelegate *scene_delegate, Object *object); static std::unique_ptr<ObjectData> init(pxr::HdSceneDelegate *scene_delegate, Object *object);
static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate, Object *object); static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate, Object *object);
@ -31,6 +29,6 @@ public:
bool visible; bool visible;
}; };
using ObjectDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<ObjectData>, pxr::SdfPath::Hash>;
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -246,7 +246,7 @@ void ViewportEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, Hd
sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(), sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(),
SdfPath::AbsoluteRootPath().AppendElementString("scene")); SdfPath::AbsoluteRootPath().AppendElementString("scene"));
} }
sceneDelegate->Populate(b_depsgraph, b_context); sceneDelegate->populate((Depsgraph *)b_depsgraph.ptr.data, (bContext *)b_context.ptr.data);
for (auto const& setting : renderSettings) { for (auto const& setting : renderSettings) {
renderDelegate->SetRenderSetting(setting.first, setting.second); renderDelegate->SetRenderSetting(setting.first, setting.second);