From dd57fa6544adddb3596493fc0f5436a748142ea2 Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Tue, 7 Mar 2023 18:44:45 +0300 Subject: [PATCH 01/11] ic --- pxr/imaging/plugin/hdRpr/CMakeLists.txt | 2 + pxr/imaging/plugin/hdRpr/renderDelegate.cpp | 3 + pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 237 +++++++++++++++++++ pxr/imaging/plugin/hdRpr/resourceWatcher.h | 21 ++ pxr/imaging/plugin/hdRpr/rprApi.cpp | 3 + 5 files changed, 266 insertions(+) create mode 100644 pxr/imaging/plugin/hdRpr/resourceWatcher.cpp create mode 100644 pxr/imaging/plugin/hdRpr/resourceWatcher.h diff --git a/pxr/imaging/plugin/hdRpr/CMakeLists.txt b/pxr/imaging/plugin/hdRpr/CMakeLists.txt index ebfd39db5..0b0f5e758 100644 --- a/pxr/imaging/plugin/hdRpr/CMakeLists.txt +++ b/pxr/imaging/plugin/hdRpr/CMakeLists.txt @@ -150,6 +150,7 @@ pxr_plugin(hdRpr PRIVATE_HEADERS baseRprim.h api.h + resourceWatcher.h RESOURCE_FILES plugInfo.json @@ -161,6 +162,7 @@ pxr_plugin(hdRpr ${CMAKE_CURRENT_BINARY_DIR}/config.cpp ndrDiscoveryPlugin.cpp ndrParserPlugin.cpp + resourceWatcher.cpp ) if(RPR_EXR_EXPORT_ENABLED) diff --git a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp index 65d2adfcb..30348ada8 100644 --- a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp +++ b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp @@ -44,6 +44,8 @@ limitations under the License. #include #include +#include "resourceWatcher.h" + PXR_NAMESPACE_OPEN_SCOPE static HdRprApi* g_rprApi = nullptr; @@ -186,6 +188,7 @@ HdRprDelegate::HdRprDelegate(HdRenderSettingsMap const& renderSettings) { } m_lastCreatedInstance = this; + InitWatcher(); } HdRprDelegate::~HdRprDelegate() { diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp new file mode 100644 index 000000000..0c781eaa1 --- /dev/null +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -0,0 +1,237 @@ +#include "resourceWatcher.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BUILD_AS_HOUDINI_PLUGIN +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#endif // BUILD_AS_HOUDINI_PLUGIN + +#ifdef GET_IS_BYPASSED +#error "GET_IS_BYPASSED is defined elsewhere" +#else +#define GET_IS_BYPASSED(classname) \ + {\ + classname* n = dynamic_cast(node); \ + if (n) { \ + hasBypassParam = true; \ + bypass = n->isBypassed(); \ + return; \ + } \ + } +#endif + +void GetBypassed(HOM_Node* node, bool& hasBypassParam, bool& bypass) { + GET_IS_BYPASSED(HOM_ChopNode) + GET_IS_BYPASSED(HOM_CopNode) + GET_IS_BYPASSED(HOM_DopNode) + GET_IS_BYPASSED(HOM_LopNode) + GET_IS_BYPASSED(HOM_RopNode) + GET_IS_BYPASSED(HOM_SopNode) + GET_IS_BYPASSED(HOM_TopNode) + GET_IS_BYPASSED(HOM_VopNode) + hasBypassParam = false; + bypass = false; +} + +#undef GET_IS_BYPASSED + +#ifdef SET_BYPASS +#error "SET_BYPASS is defined elsewhere" +#else +#define SET_BYPASS(classname) \ + {\ + classname* n = dynamic_cast(node); \ + if (n) { \ + n->bypass(bypass); \ + return; \ + } \ + } +#endif + +void SetBypassed(HOM_Node* node, bool bypass) { + SET_BYPASS(HOM_ChopNode) + SET_BYPASS(HOM_CopNode) + SET_BYPASS(HOM_DopNode) + SET_BYPASS(HOM_LopNode) + SET_BYPASS(HOM_RopNode) + SET_BYPASS(HOM_SopNode) + SET_BYPASS(HOM_TopNode) + SET_BYPASS(HOM_VopNode) +} + +#undef SET_BYPASS + +typedef std::map NodesToRestoreSet; + +void DeActivateScene(NodesToRestoreSet& nodesToRestore) { + nodesToRestore.clear(); + HOM_Module& hom = HOM(); + HOM_Node* root = hom.root(); + auto children = root->children(); + for (HOM_ElemPtr& c : children) { + if (c.myPointer->name() == "stage") { + auto schildren = c.myPointer->children(); + for (HOM_ElemPtr& sc : schildren) { + //fprintf(stdout, "sc %s\n", sc.myPointer->name().c_str()); + bool hasBypassParam; + bool bypass; + GetBypassed(sc.myPointer, hasBypassParam, bypass); + if (hasBypassParam) { + nodesToRestore.emplace(sc.myPointer->name(), bypass); + } + } + } + } +} + +void ActivateScene(NodesToRestoreSet& nodesToRestore) { + HOM_Module& hom = HOM(); + HOM_Node* root = hom.root(); + auto children = root->children(); + for (HOM_ElemPtr& c : children) { + if (c.myPointer->name() == "stage") { + auto schildren = c.myPointer->children(); + for (HOM_ElemPtr& sc : schildren) { + auto it = nodesToRestore.find(sc.myPointer->name()); + if (it != nodesToRestore.end()) { + SetBypassed(sc.myPointer, (*it).second); + } + } + } + } +} + +using namespace hboost::interprocess; + +struct MessageData { + ipcdetail::OS_process_id_t pid; + bool started; +}; + +struct InterprocessMessage +{ + InterprocessMessage() : message_in(false) {} + hboost::interprocess::interprocess_mutex mutex; + hboost::interprocess::interprocess_condition cond_empty; + hboost::interprocess::interprocess_condition cond_full; + MessageData content; + bool message_in; +}; + +class ResourceWatcher { +public: + ResourceWatcher(): m_shm(open_or_create, "RprResourceWatcher", read_write), m_message(nullptr) {} + ~ResourceWatcher() { + if (m_message) { + m_message->~InterprocessMessage(); + } + shared_memory_object::remove("RprResourceWatcher"); + } + + bool Init() { + try { + m_shm.truncate(sizeof(InterprocessMessage)); + m_region = std::make_unique(m_shm, read_write); + void* addr = m_region->get_address(); + m_message = new (addr) InterprocessMessage; + } + catch (interprocess_exception& ex) { + std::cout << "Resource watcher failure: " << ex.what() << std::endl; + return false; + } + return true; + } + + InterprocessMessage* GetInterprocMessage() { return m_message; } +private: + shared_memory_object m_shm; + std::unique_ptr m_region; + InterprocessMessage* m_message; +}; + +static ResourceWatcher resourceWatcher; +static std::thread* listenerThread = nullptr; + +void Listen(InterprocessMessage* message) +{ + static NodesToRestoreSet nodesToRestore; + + try { + do { + scoped_lock lock(message->mutex); + if (!message->message_in) { + message->cond_empty.wait(lock); + } + else { + if (message->content.pid != hboost::interprocess::ipcdetail::get_current_process_id()) { // Ignore messages from the same process + if (message->content.started) { + DeActivateScene(nodesToRestore); + } + else { + ActivateScene(nodesToRestore); + } + } + + message->message_in = false; + message->cond_full.notify_all(); + } + } while (true); + } + catch (interprocess_exception& ex) { + std::cout << "Resource watcher failure: " << ex.what() << std::endl; + } +} + + +void InitWatcher() { + if (!listenerThread) { + resourceWatcher.Init(); + listenerThread = new std::thread(Listen, resourceWatcher.GetInterprocMessage()); + } +} + +void Notify(InterprocessMessage* message, bool started) { + try { + scoped_lock lock(message->mutex); + if (message->message_in) { + message->cond_full.wait(lock); + } + message->content.pid = hboost::interprocess::ipcdetail::get_current_process_id(); + message->content.started = started; + + //Notify to the other process that there is a message + message->cond_empty.notify_all(); + + //Mark message buffer as full + message->message_in = true; + } + catch (interprocess_exception& ex) { + std::cout << ex.what() << std::endl; + } +} + +void NotifyRenderStarted() { + Notify(resourceWatcher.GetInterprocMessage(), true); +} + +void NotifyRenderFinished() { + Notify(resourceWatcher.GetInterprocMessage(), false); +} diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.h b/pxr/imaging/plugin/hdRpr/resourceWatcher.h new file mode 100644 index 000000000..8a35fad22 --- /dev/null +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.h @@ -0,0 +1,21 @@ +/************************************************************************ +Copyright 2023 Advanced Micro Devices, Inc +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************/ + +#ifndef RESOURCE_WATCHER_H +#define RESOURCE_WATCHER_H + +void InitWatcher(); +void NotifyRenderStarted(); +void NotifyRenderFinished(); + +#endif // RESOURCE_WATCHER_H \ No newline at end of file diff --git a/pxr/imaging/plugin/hdRpr/rprApi.cpp b/pxr/imaging/plugin/hdRpr/rprApi.cpp index 82960dc2e..63279537d 100644 --- a/pxr/imaging/plugin/hdRpr/rprApi.cpp +++ b/pxr/imaging/plugin/hdRpr/rprApi.cpp @@ -58,6 +58,7 @@ using json = nlohmann::json; #include "pxr/base/tf/envSetting.h" #include "notify/message.h" +#include "resourceWatcher.h" #include #include @@ -3306,6 +3307,7 @@ Don't show this message again? } void Render(HdRprRenderThread* renderThread) { + NotifyRenderStarted(); RenderFrame(renderThread); for (auto& aovBinding : m_aovBindings) { @@ -3313,6 +3315,7 @@ Don't show this message again? rb->SetConverged(true); } } + NotifyRenderFinished(); } void AbortRender() { From 44fd57d5c123d8949cc7d2529eb43bb1b78aea0c Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Sun, 12 Mar 2023 15:33:25 +0300 Subject: [PATCH 02/11] bypass setting --- pxr/imaging/plugin/hdRpr/renderDelegate.cpp | 1 + pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 39 +++++++++++++++++--- pxr/imaging/plugin/hdRpr/rprApi.cpp | 1 - 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp index 30348ada8..d67b1fd38 100644 --- a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp +++ b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp @@ -192,6 +192,7 @@ HdRprDelegate::HdRprDelegate(HdRenderSettingsMap const& renderSettings) { } HdRprDelegate::~HdRprDelegate() { + NotifyRenderFinished(); g_rprApi = nullptr; m_lastCreatedInstance = nullptr; } diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 0c781eaa1..ffde7e3fb 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -1,5 +1,6 @@ #include "resourceWatcher.h" +#ifdef BUILD_AS_HOUDINI_PLUGIN #include #include #include @@ -10,9 +11,10 @@ #include #include -#ifdef BUILD_AS_HOUDINI_PLUGIN #include #include +#include +#include #include #include @@ -22,7 +24,6 @@ #include #include #include -#endif // BUILD_AS_HOUDINI_PLUGIN #ifdef GET_IS_BYPASSED #error "GET_IS_BYPASSED is defined elsewhere" @@ -84,26 +85,40 @@ typedef std::map NodesToRestoreSet; void DeActivateScene(NodesToRestoreSet& nodesToRestore) { nodesToRestore.clear(); HOM_Module& hom = HOM(); + if (hom.applicationName().rfind("houdini", 0) != 0) { + return; + } + HOM_Node* root = hom.root(); auto children = root->children(); for (HOM_ElemPtr& c : children) { if (c.myPointer->name() == "stage") { auto schildren = c.myPointer->children(); for (HOM_ElemPtr& sc : schildren) { - //fprintf(stdout, "sc %s\n", sc.myPointer->name().c_str()); bool hasBypassParam; bool bypass; GetBypassed(sc.myPointer, hasBypassParam, bypass); if (hasBypassParam) { nodesToRestore.emplace(sc.myPointer->name(), bypass); + SetBypassed(sc.myPointer, true); } } } } + + HOM_ui& ui = hom.ui(); + HOM_SceneViewer* sceneViewer = dynamic_cast(ui.paneTabOfType(HOM_paneTabType::SceneViewer)); + if (sceneViewer) { + sceneViewer->restartRenderer(); + } } void ActivateScene(NodesToRestoreSet& nodesToRestore) { HOM_Module& hom = HOM(); + if (hom.applicationName().rfind("houdini", 0) != 0) { + return; + } + HOM_Node* root = hom.root(); auto children = root->children(); for (HOM_ElemPtr& c : children) { @@ -136,14 +151,19 @@ struct InterprocessMessage bool message_in; }; +void Notify(InterprocessMessage* message, bool started); + class ResourceWatcher { public: ResourceWatcher(): m_shm(open_or_create, "RprResourceWatcher", read_write), m_message(nullptr) {} ~ResourceWatcher() { + try { + Notify(m_message, false); + } + catch (...) {} if (m_message) { m_message->~InterprocessMessage(); } - shared_memory_object::remove("RprResourceWatcher"); } bool Init() { @@ -173,7 +193,6 @@ static std::thread* listenerThread = nullptr; void Listen(InterprocessMessage* message) { static NodesToRestoreSet nodesToRestore; - try { do { scoped_lock lock(message->mutex); @@ -183,6 +202,7 @@ void Listen(InterprocessMessage* message) else { if (message->content.pid != hboost::interprocess::ipcdetail::get_current_process_id()) { // Ignore messages from the same process if (message->content.started) { + fprintf(stdout, "RCV\n"); DeActivateScene(nodesToRestore); } else { @@ -200,7 +220,6 @@ void Listen(InterprocessMessage* message) } } - void InitWatcher() { if (!listenerThread) { resourceWatcher.Init(); @@ -235,3 +254,11 @@ void NotifyRenderStarted() { void NotifyRenderFinished() { Notify(resourceWatcher.GetInterprocMessage(), false); } + +#else + +void InitWatcher() {} +void NotifyRenderStarted() {} +void NotifyRenderFinished() {} + +#endif // BUILD_AS_HOUDINI_PLUGIN diff --git a/pxr/imaging/plugin/hdRpr/rprApi.cpp b/pxr/imaging/plugin/hdRpr/rprApi.cpp index 63279537d..57d70eb71 100644 --- a/pxr/imaging/plugin/hdRpr/rprApi.cpp +++ b/pxr/imaging/plugin/hdRpr/rprApi.cpp @@ -3315,7 +3315,6 @@ Don't show this message again? rb->SetConverged(true); } } - NotifyRenderFinished(); } void AbortRender() { From ef3ae7c748d82656e1fdcc3cee80dada92c6ff4b Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Mon, 27 Mar 2023 18:10:12 +0300 Subject: [PATCH 03/11] pause processing --- pxr/imaging/plugin/hdRpr/renderDelegate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp index d67b1fd38..ab35512b4 100644 --- a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp +++ b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp @@ -380,11 +380,13 @@ bool HdRprDelegate::IsPauseSupported() const { } bool HdRprDelegate::Pause() { + NotifyRenderFinished(); m_renderThread.PauseRender(); return true; } bool HdRprDelegate::Resume() { + NotifyRenderStarted(); m_renderThread.ResumeRender(); return true; } From b378271f7b4759aeab42ac7f44deaa73bb7c45a7 Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Thu, 30 Mar 2023 20:22:53 +0300 Subject: [PATCH 04/11] namespace change --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index ffde7e3fb..6e52f940f 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -134,10 +134,8 @@ void ActivateScene(NodesToRestoreSet& nodesToRestore) { } } -using namespace hboost::interprocess; - struct MessageData { - ipcdetail::OS_process_id_t pid; + hboost::interprocess::ipcdetail::OS_process_id_t pid; bool started; }; @@ -155,7 +153,7 @@ void Notify(InterprocessMessage* message, bool started); class ResourceWatcher { public: - ResourceWatcher(): m_shm(open_or_create, "RprResourceWatcher", read_write), m_message(nullptr) {} + ResourceWatcher(): m_shm(hboost::interprocess::open_or_create, "RprResourceWatcher", hboost::interprocess::read_write), m_message(nullptr) {} ~ResourceWatcher() { try { Notify(m_message, false); @@ -169,11 +167,11 @@ class ResourceWatcher { bool Init() { try { m_shm.truncate(sizeof(InterprocessMessage)); - m_region = std::make_unique(m_shm, read_write); + m_region = std::make_unique(m_shm, hboost::interprocess::read_write); void* addr = m_region->get_address(); m_message = new (addr) InterprocessMessage; } - catch (interprocess_exception& ex) { + catch (hboost::interprocess::interprocess_exception& ex) { std::cout << "Resource watcher failure: " << ex.what() << std::endl; return false; } @@ -182,8 +180,8 @@ class ResourceWatcher { InterprocessMessage* GetInterprocMessage() { return m_message; } private: - shared_memory_object m_shm; - std::unique_ptr m_region; + hboost::interprocess::shared_memory_object m_shm; + std::unique_ptr m_region; InterprocessMessage* m_message; }; @@ -195,7 +193,7 @@ void Listen(InterprocessMessage* message) static NodesToRestoreSet nodesToRestore; try { do { - scoped_lock lock(message->mutex); + hboost::interprocess::scoped_lock lock(message->mutex); if (!message->message_in) { message->cond_empty.wait(lock); } @@ -215,7 +213,7 @@ void Listen(InterprocessMessage* message) } } while (true); } - catch (interprocess_exception& ex) { + catch (hboost::interprocess::interprocess_exception& ex) { std::cout << "Resource watcher failure: " << ex.what() << std::endl; } } @@ -229,7 +227,7 @@ void InitWatcher() { void Notify(InterprocessMessage* message, bool started) { try { - scoped_lock lock(message->mutex); + hboost::interprocess::scoped_lock lock(message->mutex); if (message->message_in) { message->cond_full.wait(lock); } @@ -242,7 +240,7 @@ void Notify(InterprocessMessage* message, bool started) { //Mark message buffer as full message->message_in = true; } - catch (interprocess_exception& ex) { + catch (hboost::interprocess::interprocess_exception& ex) { std::cout << ex.what() << std::endl; } } From b1e17e05447dc7e5c7c8659eac289cb14fb76754 Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Thu, 30 Mar 2023 21:30:58 +0300 Subject: [PATCH 05/11] namespace test --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 6e52f940f..07add7924 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -135,6 +135,13 @@ void ActivateScene(NodesToRestoreSet& nodesToRestore) { } struct MessageData { +#if defined (HBOOST_INTERPROCESS_WINDOWS) +#pragma message(">>> Windows build") +#else +#pragma message(">>> Linux build") +#endif + pid_t _pid; + hboost::interprocess::ipcdetail::OS_thread_t tid; hboost::interprocess::ipcdetail::OS_process_id_t pid; bool started; }; From 73376ed2c47bf60f1eae966d39e64e6d15a7384d Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Fri, 31 Mar 2023 01:37:40 +0300 Subject: [PATCH 06/11] ubuntu deps fix --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 07add7924..3a4c230b4 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -135,13 +136,6 @@ void ActivateScene(NodesToRestoreSet& nodesToRestore) { } struct MessageData { -#if defined (HBOOST_INTERPROCESS_WINDOWS) -#pragma message(">>> Windows build") -#else -#pragma message(">>> Linux build") -#endif - pid_t _pid; - hboost::interprocess::ipcdetail::OS_thread_t tid; hboost::interprocess::ipcdetail::OS_process_id_t pid; bool started; }; From 89129c4b96675502c638caa4965cfe74231aa69f Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Thu, 20 Apr 2023 01:25:32 +0300 Subject: [PATCH 07/11] restore with timeout & enabling feature by user --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 172 ++++++++++++++---- pxr/imaging/plugin/hdRpr/resourceWatcher.h | 6 + .../plugin/rprHoudini/ui/MainMenuCommon.xml | 15 ++ pxr/imaging/rprUsd/config.cpp | 15 ++ pxr/imaging/rprUsd/config.h | 5 + 5 files changed, 175 insertions(+), 38 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 3a4c230b4..8d8cb58f2 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -3,6 +3,7 @@ #ifdef BUILD_AS_HOUDINI_PLUGIN #include #include +#include #include #include #include @@ -25,6 +26,12 @@ #include #include #include +#include "pxr/base/arch/env.h" +#include "pxr/imaging/rprUsd/config.h" +#include +namespace fs = ghc::filesystem; + +PXR_NAMESPACE_OPEN_SCOPE #ifdef GET_IS_BYPASSED #error "GET_IS_BYPASSED is defined elsewhere" @@ -83,10 +90,41 @@ void SetBypassed(HOM_Node* node, bool bypass) { typedef std::map NodesToRestoreSet; +bool ResourceManagementActive(HOM_Module& hom) { + auto result = hom.hscript("if( $RPR_MEM_MANAGEMENT ) then\necho 1;\nelse\necho 0;\nendif"); + return result.size() > 0 && result[0].size() > 0 && result[0][0] == '1'; +} + +void ReadMemManagementFlag() { + HOM_Module& hom = HOM(); + RprUsdConfig* config; + auto configLock = RprUsdConfig::GetInstance(&config); + hom.hscript(config->GetMemManagement() ? "set -g RPR_MEM_MANAGEMENT = 1" : "set -g RPR_MEM_MANAGEMENT = 0"); + hom.hscript("varchange RPR_MEM_MANAGEMENT"); +} + +void WriteMemManagementFlag() { + HOM_Module& hom = HOM(); + RprUsdConfig* config; + auto configLock = RprUsdConfig::GetInstance(&config); + config->SetMemManagement(ResourceManagementActive(hom)); +} + +bool IsHoudiniInstance() { + static bool tested = false; + static bool isHoudiniInstance = false; + if (!tested) { + HOM_Module& hom = HOM(); + isHoudiniInstance = hom.applicationName().rfind("houdini", 0) == 0; + } + return isHoudiniInstance; +} + void DeActivateScene(NodesToRestoreSet& nodesToRestore) { - nodesToRestore.clear(); HOM_Module& hom = HOM(); - if (hom.applicationName().rfind("houdini", 0) != 0) { + if (nodesToRestore.size() != 0 // already deactivated + || !IsHoudiniInstance() || ResourceManagementActive(hom)) + { return; } @@ -115,11 +153,12 @@ void DeActivateScene(NodesToRestoreSet& nodesToRestore) { } void ActivateScene(NodesToRestoreSet& nodesToRestore) { - HOM_Module& hom = HOM(); - if (hom.applicationName().rfind("houdini", 0) != 0) { + if (!IsHoudiniInstance()) + { return; } + HOM_Module& hom = HOM(); HOM_Node* root = hom.root(); auto children = root->children(); for (HOM_ElemPtr& c : children) { @@ -133,21 +172,24 @@ void ActivateScene(NodesToRestoreSet& nodesToRestore) { } } } + nodesToRestore.clear(); } +enum class MessageType { Started, Finished, Live }; + struct MessageData { hboost::interprocess::ipcdetail::OS_process_id_t pid; - bool started; + MessageType messageType; }; struct InterprocessMessage { - InterprocessMessage() : message_in(false) {} + InterprocessMessage() : messageIn(false) {} hboost::interprocess::interprocess_mutex mutex; - hboost::interprocess::interprocess_condition cond_empty; - hboost::interprocess::interprocess_condition cond_full; + hboost::interprocess::interprocess_condition condEmpty; + hboost::interprocess::interprocess_condition condFull; MessageData content; - bool message_in; + bool messageIn; }; void Notify(InterprocessMessage* message, bool started); @@ -155,18 +197,10 @@ void Notify(InterprocessMessage* message, bool started); class ResourceWatcher { public: ResourceWatcher(): m_shm(hboost::interprocess::open_or_create, "RprResourceWatcher", hboost::interprocess::read_write), m_message(nullptr) {} - ~ResourceWatcher() { - try { - Notify(m_message, false); - } - catch (...) {} - if (m_message) { - m_message->~InterprocessMessage(); - } - } bool Init() { try { + ReadMemManagementFlag(); m_shm.truncate(sizeof(InterprocessMessage)); m_region = std::make_unique(m_shm, hboost::interprocess::read_write); void* addr = m_region->get_address(); @@ -188,29 +222,40 @@ class ResourceWatcher { static ResourceWatcher resourceWatcher; static std::thread* listenerThread = nullptr; +static std::thread* checkAliveThread = nullptr; +std::mutex timePointsLock; +std::map timePoints; +NodesToRestoreSet nodesToRestore; void Listen(InterprocessMessage* message) { - static NodesToRestoreSet nodesToRestore; try { do { hboost::interprocess::scoped_lock lock(message->mutex); - if (!message->message_in) { - message->cond_empty.wait(lock); + if (!message->messageIn) { + message->condEmpty.wait(lock); } else { if (message->content.pid != hboost::interprocess::ipcdetail::get_current_process_id()) { // Ignore messages from the same process - if (message->content.started) { + if (message->content.messageType == MessageType::Started) { fprintf(stdout, "RCV\n"); + std::lock_guard lock(timePointsLock); + timePoints[message->content.pid] = std::chrono::steady_clock::now(); DeActivateScene(nodesToRestore); } - else { + else if (message->content.messageType == MessageType::Finished) { + std::lock_guard lock(timePointsLock); + timePoints.erase(message->content.pid); ActivateScene(nodesToRestore); } + else if (message->content.messageType == MessageType::Live) { + std::lock_guard lock(timePointsLock); + timePoints[message->content.pid] = std::chrono::steady_clock::now(); + } } - message->message_in = false; - message->cond_full.notify_all(); + message->messageIn = false; + message->condFull.notify_all(); } } while (true); } @@ -219,45 +264,96 @@ void Listen(InterprocessMessage* message) } } -void InitWatcher() { - if (!listenerThread) { - resourceWatcher.Init(); - listenerThread = new std::thread(Listen, resourceWatcher.GetInterprocMessage()); +void NotifyLive(InterprocessMessage* message) { + try { + auto pid = hboost::interprocess::ipcdetail::get_current_process_id(); + while (true) { + { // code block where the mutex is locked + hboost::interprocess::scoped_lock lock(message->mutex); + if (message->messageIn) { + message->condFull.wait(lock); + } + message->content.pid = pid; + message->content.messageType = MessageType::Live; + message->condEmpty.notify_all(); + message->messageIn = true; + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + catch (hboost::interprocess::interprocess_exception& ex) { + std::cout << ex.what() << std::endl; + } +} + +void CheckLive(InterprocessMessage* message) { + while (true) { + { // code block where the mutex is locked + std::lock_guard lock(timePointsLock); + bool anyAlive = false; + for (auto it = timePoints.begin(); it != timePoints.end(); ++it) { + auto interval = std::chrono::steady_clock::now().time_since_epoch() - (*it).second.time_since_epoch(); + double seconds = (double)interval.count() / 1000000000.0; + int maxTimeoutSeconds = 3; + if (seconds < maxTimeoutSeconds) { + anyAlive = true; + break; + } + } + if (!anyAlive) { + timePoints.clear(); + if (nodesToRestore.size() != 0) { + ActivateScene(nodesToRestore); + } + } + } + std::this_thread::sleep_for(std::chrono::seconds(1)); } } void Notify(InterprocessMessage* message, bool started) { try { hboost::interprocess::scoped_lock lock(message->mutex); - if (message->message_in) { - message->cond_full.wait(lock); + if (message->messageIn) { + message->condFull.wait(lock); } message->content.pid = hboost::interprocess::ipcdetail::get_current_process_id(); - message->content.started = started; - - //Notify to the other process that there is a message - message->cond_empty.notify_all(); - - //Mark message buffer as full - message->message_in = true; + message->content.messageType = started ? MessageType::Started : MessageType::Finished; + message->condEmpty.notify_all(); + message->messageIn = true; } catch (hboost::interprocess::interprocess_exception& ex) { std::cout << ex.what() << std::endl; } } +void InitWatcher() { + if (!checkAliveThread) { + resourceWatcher.Init(); + checkAliveThread = new std::thread(IsHoudiniInstance() ? CheckLive : NotifyLive, resourceWatcher.GetInterprocMessage()); + } + if (!listenerThread) { + listenerThread = new std::thread(Listen, resourceWatcher.GetInterprocMessage()); + } +} + void NotifyRenderStarted() { Notify(resourceWatcher.GetInterprocMessage(), true); } void NotifyRenderFinished() { + WriteMemManagementFlag(); // calls on render delegate destructor, just as needed Notify(resourceWatcher.GetInterprocMessage(), false); } #else +PXR_NAMESPACE_OPEN_SCOPE + void InitWatcher() {} void NotifyRenderStarted() {} void NotifyRenderFinished() {} #endif // BUILD_AS_HOUDINI_PLUGIN + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.h b/pxr/imaging/plugin/hdRpr/resourceWatcher.h index 8a35fad22..b5704211b 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.h +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.h @@ -14,8 +14,14 @@ limitations under the License. #ifndef RESOURCE_WATCHER_H #define RESOURCE_WATCHER_H +#include "pxr/imaging/rprUsd/api.h" + +PXR_NAMESPACE_OPEN_SCOPE + void InitWatcher(); void NotifyRenderStarted(); void NotifyRenderFinished(); +PXR_NAMESPACE_CLOSE_SCOPE + #endif // RESOURCE_WATCHER_H \ No newline at end of file diff --git a/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml b/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml index 56940adfb..859d45839 100644 --- a/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml +++ b/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml @@ -50,6 +50,21 @@ + + + RPR_MEM_MANAGEMENT + + + diff --git a/pxr/imaging/rprUsd/config.cpp b/pxr/imaging/rprUsd/config.cpp index 1d35c813d..8fdf52e63 100644 --- a/pxr/imaging/rprUsd/config.cpp +++ b/pxr/imaging/rprUsd/config.cpp @@ -153,6 +153,7 @@ bool GetJsonProperty(const char* propertyName, json const& json, T* property) { const char* kShowRestartRequiredMessage = "ShowRestartRequiredMessage"; const char* kTextureCacheDir = "TextureCacheDir"; const char* kKernelCacheDir = "KernelCacheDir"; +const char* kMemManagement = "MemManagement"; } // namespace anonymous @@ -235,6 +236,7 @@ void RprUsdConfig::SetKernelCacheDir(std::string const& newValue) { Save(); } } + std::string RprUsdConfig::GetKernelCacheDir() const { std::string ret; if (!GetJsonProperty(kKernelCacheDir, m_impl->cfg, &ret)) { @@ -243,6 +245,19 @@ std::string RprUsdConfig::GetKernelCacheDir() const { return ret; } +bool RprUsdConfig::GetMemManagement() const { + bool ret = false; + GetJsonProperty(kMemManagement, m_impl->cfg, &ret); + return ret; +} + +void RprUsdConfig::SetMemManagement(bool newValue) { + if (m_impl->cfg[kMemManagement] != newValue) { + m_impl->cfg[kMemManagement] = newValue; + Save(); + } +} + std::string RprUsdConfig::GetDeviceConfigurationFilepath() const { std::string configCacheDir = GetDefaultCacheDir("config"); return configCacheDir + ARCH_PATH_SEP + "devicesConfig.txt"; diff --git a/pxr/imaging/rprUsd/config.h b/pxr/imaging/rprUsd/config.h index c05ac68fb..60771cb52 100644 --- a/pxr/imaging/rprUsd/config.h +++ b/pxr/imaging/rprUsd/config.h @@ -48,6 +48,11 @@ class RprUsdConfig { RPRUSD_API void SetKernelCacheDir(std::string const&); + RPRUSD_API + bool GetMemManagement() const; + RPRUSD_API + void SetMemManagement(bool); + RPRUSD_API std::string GetDeviceConfigurationFilepath() const; From d41a328e936fdde71a8b6a151820a83fa682eba4 Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Thu, 8 Jun 2023 08:58:59 +0300 Subject: [PATCH 08/11] deadlock fix --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 8d8cb58f2..107cff2df 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -90,6 +90,8 @@ void SetBypassed(HOM_Node* node, bool bypass) { typedef std::map NodesToRestoreSet; +bool updateLock = false; + bool ResourceManagementActive(HOM_Module& hom) { auto result = hom.hscript("if( $RPR_MEM_MANAGEMENT ) then\necho 1;\nelse\necho 0;\nendif"); return result.size() > 0 && result[0].size() > 0 && result[0][0] == '1'; @@ -123,7 +125,7 @@ bool IsHoudiniInstance() { void DeActivateScene(NodesToRestoreSet& nodesToRestore) { HOM_Module& hom = HOM(); if (nodesToRestore.size() != 0 // already deactivated - || !IsHoudiniInstance() || ResourceManagementActive(hom)) + || !IsHoudiniInstance() || !ResourceManagementActive(hom)) { return; } @@ -238,15 +240,18 @@ void Listen(InterprocessMessage* message) else { if (message->content.pid != hboost::interprocess::ipcdetail::get_current_process_id()) { // Ignore messages from the same process if (message->content.messageType == MessageType::Started) { - fprintf(stdout, "RCV\n"); std::lock_guard lock(timePointsLock); timePoints[message->content.pid] = std::chrono::steady_clock::now(); + updateLock = true; DeActivateScene(nodesToRestore); + updateLock = false; } else if (message->content.messageType == MessageType::Finished) { std::lock_guard lock(timePointsLock); timePoints.erase(message->content.pid); + updateLock = true; ActivateScene(nodesToRestore); + updateLock = false; } else if (message->content.messageType == MessageType::Live) { std::lock_guard lock(timePointsLock); @@ -312,6 +317,9 @@ void CheckLive(InterprocessMessage* message) { } void Notify(InterprocessMessage* message, bool started) { + if (updateLock) { + return; + } try { hboost::interprocess::scoped_lock lock(message->mutex); if (message->messageIn) { From d87f6d2f71bca84cb1291e065685e3d637a93d4e Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Wed, 12 Jul 2023 01:32:04 +0300 Subject: [PATCH 09/11] menu label changed --- pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml b/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml index 859d45839..46a2c7569 100644 --- a/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml +++ b/pxr/imaging/plugin/rprHoudini/ui/MainMenuCommon.xml @@ -51,7 +51,7 @@ - + RPR_MEM_MANAGEMENT Date: Mon, 17 Jul 2023 20:49:42 +0300 Subject: [PATCH 10/11] files excluded from non-houdini build --- pxr/imaging/plugin/hdRpr/CMakeLists.txt | 9 +++++++-- pxr/imaging/plugin/hdRpr/renderDelegate.cpp | 10 ++++++++++ pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 11 ----------- pxr/imaging/plugin/hdRpr/rprApi.cpp | 2 ++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/CMakeLists.txt b/pxr/imaging/plugin/hdRpr/CMakeLists.txt index abd58b33a..a1fb294eb 100644 --- a/pxr/imaging/plugin/hdRpr/CMakeLists.txt +++ b/pxr/imaging/plugin/hdRpr/CMakeLists.txt @@ -88,6 +88,11 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/rif_models.version ${RIF_VERSION_STRING}) list(APPEND RIF_MODEL_RESOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/rif_models.version${_sep}rif_models/rif_models.version") +if(HoudiniUSD_FOUND) + set(RESOURCE_WATCHER_H resourceWatcher.h) + set(RESOURCE_WATCHER_CPP resourceWatcher.cpp) +endif() + pxr_plugin(hdRpr DISABLE_PRECOMPILED_HEADERS @@ -152,7 +157,7 @@ pxr_plugin(hdRpr PRIVATE_HEADERS baseRprim.h api.h - resourceWatcher.h + ${RESOURCE_WATCHER_H} RESOURCE_FILES plugInfo.json @@ -164,7 +169,7 @@ pxr_plugin(hdRpr ${CMAKE_CURRENT_BINARY_DIR}/config.cpp ndrDiscoveryPlugin.cpp ndrParserPlugin.cpp - resourceWatcher.cpp + ${RESOURCE_WATCHER_CPP} ) if(RPR_EXR_EXPORT_ENABLED) diff --git a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp index 0028b0abf..43480268b 100644 --- a/pxr/imaging/plugin/hdRpr/renderDelegate.cpp +++ b/pxr/imaging/plugin/hdRpr/renderDelegate.cpp @@ -44,7 +44,9 @@ limitations under the License. #include #include +#ifdef BUILD_AS_HOUDINI_PLUGIN #include "resourceWatcher.h" +#endif PXR_NAMESPACE_OPEN_SCOPE @@ -188,11 +190,15 @@ HdRprDelegate::HdRprDelegate(HdRenderSettingsMap const& renderSettings) { } m_lastCreatedInstance = this; +#ifdef BUILD_AS_HOUDINI_PLUGIN InitWatcher(); +#endif } HdRprDelegate::~HdRprDelegate() { +#ifdef BUILD_AS_HOUDINI_PLUGIN NotifyRenderFinished(); +#endif g_rprApi = nullptr; m_lastCreatedInstance = nullptr; } @@ -390,13 +396,17 @@ bool HdRprDelegate::IsPauseSupported() const { } bool HdRprDelegate::Pause() { +#ifdef BUILD_AS_HOUDINI_PLUGIN NotifyRenderFinished(); +#endif m_renderThread.PauseRender(); return true; } bool HdRprDelegate::Resume() { +#ifdef BUILD_AS_HOUDINI_PLUGIN NotifyRenderStarted(); +#endif m_renderThread.ResumeRender(); return true; } diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index 107cff2df..fc5e18fa4 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -1,6 +1,5 @@ #include "resourceWatcher.h" -#ifdef BUILD_AS_HOUDINI_PLUGIN #include #include #include @@ -354,14 +353,4 @@ void NotifyRenderFinished() { Notify(resourceWatcher.GetInterprocMessage(), false); } -#else - -PXR_NAMESPACE_OPEN_SCOPE - -void InitWatcher() {} -void NotifyRenderStarted() {} -void NotifyRenderFinished() {} - -#endif // BUILD_AS_HOUDINI_PLUGIN - PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/plugin/hdRpr/rprApi.cpp b/pxr/imaging/plugin/hdRpr/rprApi.cpp index 212a644a7..be27992fd 100644 --- a/pxr/imaging/plugin/hdRpr/rprApi.cpp +++ b/pxr/imaging/plugin/hdRpr/rprApi.cpp @@ -3436,7 +3436,9 @@ Don't show this message again? } void Render(HdRprRenderThread* renderThread) { +#ifdef BUILD_AS_HOUDINI_PLUGIN NotifyRenderStarted(); +#endif updateSyncTime(); m_startTime = std::chrono::high_resolution_clock::now(); RenderFrame(renderThread); From 1675d73222054f4706dbdd546ceb8730d3f54f69 Mon Sep 17 00:00:00 2001 From: dmitrii-z Date: Fri, 1 Sep 2023 15:28:33 +0300 Subject: [PATCH 11/11] timeouts update --- pxr/imaging/plugin/hdRpr/resourceWatcher.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp index fc5e18fa4..482f87c80 100644 --- a/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp +++ b/pxr/imaging/plugin/hdRpr/resourceWatcher.cpp @@ -242,6 +242,7 @@ void Listen(InterprocessMessage* message) std::lock_guard lock(timePointsLock); timePoints[message->content.pid] = std::chrono::steady_clock::now(); updateLock = true; + fprintf(stdout, "Deactivate %d\n", message->content.pid); DeActivateScene(nodesToRestore); updateLock = false; } @@ -253,6 +254,7 @@ void Listen(InterprocessMessage* message) updateLock = false; } else if (message->content.messageType == MessageType::Live) { + fprintf(stdout, "Live %d\n", message->content.pid); std::lock_guard lock(timePointsLock); timePoints[message->content.pid] = std::chrono::steady_clock::now(); } @@ -282,7 +284,7 @@ void NotifyLive(InterprocessMessage* message) { message->condEmpty.notify_all(); message->messageIn = true; } - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } } catch (hboost::interprocess::interprocess_exception& ex) { @@ -298,7 +300,7 @@ void CheckLive(InterprocessMessage* message) { for (auto it = timePoints.begin(); it != timePoints.end(); ++it) { auto interval = std::chrono::steady_clock::now().time_since_epoch() - (*it).second.time_since_epoch(); double seconds = (double)interval.count() / 1000000000.0; - int maxTimeoutSeconds = 3; + int maxTimeoutSeconds = 5; if (seconds < maxTimeoutSeconds) { anyAlive = true; break;