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/world.h
sceneDelegate/world.cc
sceneDelegate/instance.h
sceneDelegate/instance.cc
)
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(),
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) {
renderDelegate->SetRenderSetting(setting.first, setting.second);

View File

@ -1,27 +1,22 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <pxr/imaging/hd/light.h>
#include <pxr/imaging/hd/material.h>
#include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/usd/usdLux/tokens.h>
#include <pxr/imaging/hdSt/tokens.h>
#include "DEG_depsgraph_query.h"
#include "DNA_scene_types.h"
#include "glog/logging.h"
#include "blenderSceneDelegate.h"
#include "object.h"
using namespace std;
using namespace pxr;
namespace blender::render::hydra {
BlenderSceneDelegate::BlenderSceneDelegate(HdRenderIndex* parentIndex, SdfPath const& delegateID)
: HdSceneDelegate(parentIndex, delegateID),
b_depsgraph(nullptr),
b_context(nullptr),
view3d(nullptr),
is_populated(false)
: HdSceneDelegate(parentIndex, delegateID)
, depsgraph(nullptr)
, context(nullptr)
, view3d(nullptr)
{
}
@ -54,16 +49,17 @@ void BlenderSceneDelegate::update_material(Material *material)
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) {
world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data);
world_data = WorldData::init(this, world, context);
world_data->insert_prim();
}
}
else {
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);
}
else {
@ -82,29 +78,53 @@ bool BlenderSceneDelegate::GetVisible(SdfPath const &id)
return object_data(id)->visible;
}
void BlenderSceneDelegate::update_collection()
void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
{
/* add new objects */
std::set<SdfPath> available_objects;
for (auto &inst : b_depsgraph->object_instances) {
if (inst.is_instance()) {
continue;
if (visibility) {
/* Check and update visibility */
for (auto &obj : objects) {
if (obj.second->update_visibility(view3d)) {
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);
}
}
ITER_END;
if (!is_populated) {
return;
}
if (remove) {
/* remove unused objects */
for (auto it = objects.begin(); it != objects.end(); ++it) {
if (available_objects.find(it->first) != available_objects.end()) {
@ -132,6 +152,7 @@ void BlenderSceneDelegate::update_collection()
it = materials.begin();
}
}
}
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();
}
bool BlenderSceneDelegate::supported_object(Object *object)
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
{
return object->type == OB_MESH ||
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;
}
bool is_populated = depsgraph != nullptr;
void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
{
LOG(INFO) << "Populate " << is_populated;
b_depsgraph = &b_deps;
b_context = &b_cont;
view3d = (View3D *)b_context->space_data().ptr.data;
depsgraph = deps;
context = cont;
view3d = CTX_wm_view3d(context);
if (!is_populated) {
/* Export initial objects */
update_collection();
update_collection(false, false);
update_world();
is_populated = true;
return;
}
@ -230,96 +238,75 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
bool do_update_collection = false;
bool do_update_visibility = false;
bool do_update_world = false;
bool transform, geometry, shading;
for (auto &update : b_depsgraph->updates) {
BL::ID id = update.id();
LOG(INFO) << "Update: " << id.name_full() << " ["
<< update.is_updated_transform()
<< update.is_updated_geometry()
<< update.is_updated_shading() << "]";
DEGIDIterData data = {0};
data.graph = depsgraph;
data.only_updated = true;
ITER_BEGIN (DEG_iterator_ids_begin,
DEG_iterator_ids_next,
DEG_iterator_ids_end,
&data, ID *, id) {
if (id.is_a(&RNA_Object)) {
Object *object = (Object *)id.ptr.data;
if (!supported_object(object)) {
continue;
transform = (id->recalc & ID_RECALC_TRANSFORM) != 0;
shading = (id->recalc & (ID_RECALC_SHADING | ID_RECALC_ANIMATION)) != 0;
geometry = (id->recalc & ID_RECALC_GEOMETRY) != 0;
LOG(INFO) << "Update: " << id->name << " [" << transform << geometry << shading << "]";
switch (GS(id->name)) {
case ID_OB: {
Object *object = (Object *)id;
if (!ObjectData::supported(object)) {
break;
}
add_update_object(object,
update.is_updated_geometry(),
update.is_updated_transform(),
update.is_updated_shading());
continue;
geometry |= (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) != 0;
add_update_object(object, geometry, transform, shading);
}
break;
if (id.is_a(&RNA_Material)) {
if (update.is_updated_shading()) {
Material *material = (Material *)id.ptr.data;
case ID_MA:
if (shading) {
Material *material = (Material *)id;
update_material(material);
}
continue;
}
break;
if (id.is_a(&RNA_Collection)) {
if (update.is_updated_transform() && update.is_updated_geometry()) {
case ID_GR:
if (transform && geometry) {
do_update_collection = true;
}
continue;
}
break;
if (id.is_a(&RNA_Scene)) {
if (!update.is_updated_geometry() && !update.is_updated_transform() && !update.is_updated_shading()) {
case ID_SCE:
if (!geometry && !transform && !shading) {
Scene *scene = (Scene *)id;
do_update_visibility = true;
Scene *scene = (Scene *)id.ptr.data;
if ((scene->world && !world_data) || (!scene->world && world_data)) {
do_update_world = true;
}
}
continue;
}
break;
if (id.is_a(&RNA_World)) {
if (update.is_updated_shading()) {
case ID_WO:
if (shading) {
do_update_world = true;
}
continue;
}
}
break;
if (do_update_collection) {
update_collection();
default:
break;
}
if (do_update_visibility) {
update_visibility();
}
ITER_END;
if (do_update_collection || do_update_visibility) {
update_collection(do_update_collection, do_update_visibility);
}
if (do_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)

View File

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

View File

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

View File

@ -12,6 +12,24 @@ using namespace pxr;
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)
{
switch (object->type) {

View File

@ -14,11 +14,9 @@
namespace blender::render::hydra {
class ObjectData;
using ObjectDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<ObjectData>, pxr::SdfPath::Hash>;
class ObjectData: public IdData {
public:
static bool supported(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);
@ -31,6 +29,6 @@ public:
bool visible;
};
using ObjectDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<ObjectData>, pxr::SdfPath::Hash>;
} // 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(),
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) {
renderDelegate->SetRenderSetting(setting.first, setting.second);