Skip to content

Commit 9b71ae8

Browse files
committed
add ability to share a live TSD scene with anari_tsd device
1 parent 7eafa19 commit 9b71ae8

File tree

17 files changed

+349
-203
lines changed

17 files changed

+349
-203
lines changed

tsd/apps/interactive/demos/viskores/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ find_package(viskores_graph 1.1.0 REQUIRED)
77
project_link_libraries(
88
tsd_ui_imgui
99
tsd_ext_imnodes
10+
tsd_core
11+
tsd_device
1012
viskores_graph::viskores_graph
1113
)
1214
project_compile_definitions(PRIVATE -DIMGUI_DEFINE_MATH_OPERATORS)

tsd/apps/interactive/demos/viskores/tsdDemoViskores.cpp

Lines changed: 157 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111
#include <tsd/ui/imgui/windows/ObjectEditor.h>
1212
#include <tsd/ui/imgui/windows/TransferFunctionEditor.h>
1313
#include <tsd/ui/imgui/windows/Viewport.h>
14+
// anari_tsd
15+
#include "anari_tsd/anariNewTsdDevice.h"
1416
// std
1517
#include <chrono>
1618

1719
#include "NodeEditor.h"
1820
#include "NodeInfoWindow.h"
1921

22+
#define TSD_DEVICE_PASSTHROUGH 1
23+
2024
namespace tsd::demo {
2125

2226
using TSDApplication = tsd::ui::imgui::Application;
@@ -25,106 +29,134 @@ namespace tsd_ui = tsd::ui::imgui;
2529
class Application : public TSDApplication
2630
{
2731
public:
28-
Application(int argc, const char *argv[]) : TSDApplication(argc, argv) {}
29-
~Application() override = default;
32+
Application(int argc, const char *argv[]);
33+
~Application() override;
3034

31-
anari_viewer::WindowArray setupWindows() override
32-
{
33-
ImNodes::CreateContext();
35+
anari_viewer::WindowArray setupWindows() override;
36+
void uiFrameEnd() override;
37+
void teardown() override;
38+
const char *getDefaultLayout() const override;
3439

35-
auto windows = TSDApplication::setupWindows();
40+
private:
41+
void setupGraph();
3642

37-
auto *core = appCore();
43+
tsd::ui::imgui::Viewport *m_viewport{nullptr};
44+
tsd::viskores_graph::NodeEditor *m_neditor{nullptr};
45+
viskores::graph::ExecutionGraph m_graph;
46+
47+
anari::Device m_tsdDevice{nullptr};
48+
anari::Frame m_tsdFrame{nullptr};
49+
};
50+
51+
// Applications definitions ///////////////////////////////////////////////////
52+
53+
Application::Application(int argc, const char *argv[])
54+
: TSDApplication(argc, argv)
55+
{}
56+
57+
Application::~Application() = default;
58+
59+
anari_viewer::WindowArray Application::setupWindows()
60+
{
61+
ImNodes::CreateContext();
62+
63+
auto windows = TSDApplication::setupWindows();
3864

39-
auto *cameras = new tsd_ui::CameraPoses(this);
40-
auto *log = new tsd_ui::Log(this);
41-
m_viewport =
42-
new tsd_ui::Viewport(this, &core->view.manipulator, "Viewport");
43-
m_viewport->setDeviceChangeCb([&](const std::string &libName) {
44-
auto &adm = appCore()->anari;
45-
auto &scene = appCore()->tsd.scene;
46-
// Use the same ANARI device for the graph as we are in the viewport
47-
m_graph.setANARIDevice(adm.loadDevice(libName));
48-
if (!libName.empty()) {
49-
tsd::core::logStatus(
50-
"[viskores] graph now using ANARI library '%s'", libName.c_str());
51-
}
52-
});
53-
auto *dbeditor = new tsd_ui::DatabaseEditor(this);
54-
auto *oeditor = new tsd_ui::ObjectEditor(this);
55-
auto *otree = new tsd_ui::LayerTree(this);
56-
auto *tfeditor = new tsd_ui::TransferFunctionEditor(this);
57-
auto *isoeditor = new tsd_ui::IsosurfaceEditor(this);
58-
59-
auto ninfo = new tsd::viskores_graph::NodeInfoWindow(this);
60-
m_neditor = new tsd::viskores_graph::NodeEditor(this, &m_graph, ninfo);
61-
62-
windows.emplace_back(cameras);
63-
windows.emplace_back(m_viewport);
64-
windows.emplace_back(dbeditor);
65-
windows.emplace_back(oeditor);
66-
windows.emplace_back(otree);
67-
windows.emplace_back(log);
68-
windows.emplace_back(tfeditor);
69-
windows.emplace_back(ninfo);
70-
windows.emplace_back(m_neditor);
71-
72-
setWindowArray(windows);
73-
74-
tfeditor->hide();
75-
76-
// Populate scene //
77-
78-
auto populateScene = [vp = m_viewport, core = core]() {
79-
auto &scene = core->tsd.scene;
80-
81-
const bool setupDefaultLight = !core->commandLine.loadedFromStateFile
82-
&& scene.numberOfObjects(ANARI_LIGHT) == 0;
83-
if (setupDefaultLight) {
84-
tsd::core::logStatus("...setting up default light");
85-
86-
auto light = scene.createObject<tsd::core::Light>(
87-
tsd::core::tokens::light::directional);
88-
light->setName("mainLight");
89-
light->setParameter("direction", tsd::math::float2(0.f, 240.f));
90-
91-
scene.defaultLayer()->root()->insert_first_child({light});
92-
}
93-
94-
core->tsd.sceneLoadComplete = true;
95-
96-
vp->setLibraryToDefault();
97-
};
65+
auto *core = appCore();
66+
67+
auto *cameras = new tsd_ui::CameraPoses(this);
68+
auto *log = new tsd_ui::Log(this);
69+
m_viewport = new tsd_ui::Viewport(this, &core->view.manipulator, "Viewport");
70+
auto *dbeditor = new tsd_ui::DatabaseEditor(this);
71+
auto *oeditor = new tsd_ui::ObjectEditor(this);
72+
auto *otree = new tsd_ui::LayerTree(this);
73+
auto *tfeditor = new tsd_ui::TransferFunctionEditor(this);
74+
auto *isoeditor = new tsd_ui::IsosurfaceEditor(this);
75+
76+
auto ninfo = new tsd::viskores_graph::NodeInfoWindow(this);
77+
m_neditor = new tsd::viskores_graph::NodeEditor(this, &m_graph, ninfo);
78+
79+
windows.emplace_back(cameras);
80+
windows.emplace_back(m_viewport);
81+
windows.emplace_back(dbeditor);
82+
windows.emplace_back(oeditor);
83+
windows.emplace_back(otree);
84+
windows.emplace_back(log);
85+
windows.emplace_back(tfeditor);
86+
windows.emplace_back(ninfo);
87+
windows.emplace_back(m_neditor);
88+
89+
setWindowArray(windows);
90+
91+
tfeditor->hide();
92+
93+
setupGraph();
94+
95+
// Populate scene //
96+
97+
auto populateScene = [vp = m_viewport, core = core]() {
98+
auto &scene = core->tsd.scene;
99+
100+
const bool setupDefaultLight = !core->commandLine.loadedFromStateFile
101+
&& scene.numberOfObjects(ANARI_LIGHT) == 0;
102+
if (setupDefaultLight) {
103+
tsd::core::logStatus("...setting up default light");
104+
105+
auto light = scene.createObject<tsd::core::Light>(
106+
tsd::core::tokens::light::directional);
107+
light->setName("mainLight");
108+
light->setParameter("direction", tsd::math::float2(0.f, 240.f));
109+
110+
scene.defaultLayer()->root()->insert_first_child({light});
111+
}
112+
113+
core->tsd.sceneLoadComplete = true;
114+
115+
vp->setLibraryToDefault();
116+
};
98117

99118
#if 1
100-
showTaskModal(populateScene, "Please Wait: Loading Scene...");
119+
showTaskModal(populateScene, "Please Wait: Loading Scene...");
101120
#else
102-
populateScene();
121+
populateScene();
103122
#endif
104123

105-
return windows;
106-
}
124+
return windows;
125+
}
107126

108-
void uiFrameEnd() override
109-
{
110-
m_graph.update(viskores::graph::GraphExecutionPolicy::ALL_ASYNC, [&]() {
111-
auto &instances = m_graph.getANARIInstances();
112-
m_viewport->setExternalInstances(instances.data(), instances.size());
113-
m_neditor->updateNodeSummary();
114-
});
115-
TSDApplication::uiFrameEnd();
116-
}
127+
void Application::uiFrameEnd()
128+
{
129+
m_graph.update(viskores::graph::GraphExecutionPolicy::ALL_ASYNC, [&]() {
130+
#if TSD_DEVICE_PASSTHROUGH
131+
anari::render(m_tsdDevice, m_tsdFrame);
132+
anari::wait(m_tsdDevice, m_tsdFrame);
133+
#if 0
134+
auto *core = appCore();
135+
core->tsd.scene.removeUnusedObjects();
136+
#endif
137+
#else
138+
auto &instances = m_graph.getANARIInstances();
139+
m_viewport->setExternalInstances(instances.data(), instances.size());
140+
#endif
141+
m_neditor->updateNodeSummary();
142+
});
143+
TSDApplication::uiFrameEnd();
144+
}
117145

118-
void teardown() override
119-
{
120-
m_graph.sync();
121-
ImNodes::DestroyContext();
122-
TSDApplication::teardown();
146+
void Application::teardown()
147+
{
148+
m_graph.sync();
149+
if (m_tsdDevice) {
150+
anari::release(m_tsdDevice, m_tsdFrame);
151+
anari::release(m_tsdDevice, m_tsdDevice);
123152
}
153+
ImNodes::DestroyContext();
154+
TSDApplication::teardown();
155+
}
124156

125-
const char *getDefaultLayout() const override
126-
{
127-
return R"layout(
157+
const char *Application::getDefaultLayout() const
158+
{
159+
return R"layout(
128160
[Window][MainDockSpace]
129161
Pos=0,26
130162
Size=1920,1105
@@ -254,13 +286,45 @@ DockSpace ID=0x80F5B4C5 Window=0x079D3A04 Pos=0,26 Size=1920,1105 Spli
254286
DockNode ID=0x0000000B Parent=0x0000000A SizeRef=550,590 Selected=0x3429FA32
255287
DockNode ID=0x0000000C Parent=0x0000000A SizeRef=550,462 Selected=0xBCE6538B
256288
)layout";
257-
}
289+
}
258290

259-
private:
260-
tsd::ui::imgui::Viewport *m_viewport{nullptr};
261-
tsd::viskores_graph::NodeEditor *m_neditor{nullptr};
262-
viskores::graph::ExecutionGraph m_graph;
263-
};
291+
void Application::setupGraph()
292+
{
293+
#if TSD_DEVICE_PASSTHROUGH
294+
anari::Device d = anariNewTsdDevice();
295+
void *scenePtr = &appCore()->tsd.scene;
296+
anari::setParameter(d, d, "scene", scenePtr);
297+
anari::commitParameters(d, d);
298+
299+
m_graph.setANARIDevice(d);
300+
301+
m_tsdFrame = anari::newObject<anari::Frame>(d);
302+
auto tsdRenderer = anari::newObject<anari::Renderer>(d, "default");
303+
auto tsdCamera = anari::newObject<anari::Camera>(d, "perspective");
304+
auto tsdWorld = m_graph.getANARIWorld();
305+
306+
anari::setParameter(d, m_tsdFrame, "renderer", tsdRenderer);
307+
anari::setParameter(d, m_tsdFrame, "camera", tsdCamera);
308+
anari::setParameter(d, m_tsdFrame, "world", tsdWorld);
309+
anari::commitParameters(d, m_tsdFrame);
310+
311+
anari::release(d, tsdRenderer);
312+
anari::release(d, tsdCamera);
313+
314+
m_tsdDevice = d;
315+
#else
316+
m_viewport->setDeviceChangeCb([&](const std::string &libName) {
317+
auto &adm = appCore()->anari;
318+
auto &scene = appCore()->tsd.scene;
319+
// Use the same ANARI device for the graph as we are in the viewport
320+
m_graph.setANARIDevice(adm.loadDevice(libName));
321+
if (!libName.empty()) {
322+
tsd::core::logStatus(
323+
"[viskores] graph now using ANARI library '%s'", libName.c_str());
324+
}
325+
});
326+
#endif
327+
}
264328

265329
} // namespace tsd::demo
266330

tsd/src/anari_tsd/Array.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Array::Array(DeviceGlobalState *state, Array1DMemoryDescriptor desc)
1212
m_deleter(desc.deleter),
1313
m_deleterPtr(desc.deleterPtr)
1414
{
15-
m_array = state->scene.createArray(desc.elementType, desc.numItems);
15+
m_array = state->scene->createArray(desc.elementType, desc.numItems);
1616
syncSharedData();
1717
}
1818

@@ -22,7 +22,7 @@ Array::Array(DeviceGlobalState *state, Array2DMemoryDescriptor desc)
2222
m_deleter(desc.deleter),
2323
m_deleterPtr(desc.deleterPtr)
2424
{
25-
m_array = state->scene.createArray(
25+
m_array = state->scene->createArray(
2626
desc.elementType, desc.numItems1, desc.numItems2);
2727
syncSharedData();
2828
}
@@ -33,7 +33,7 @@ Array::Array(DeviceGlobalState *state, Array3DMemoryDescriptor desc)
3333
m_deleter(desc.deleter),
3434
m_deleterPtr(desc.deleterPtr)
3535
{
36-
m_array = state->scene.createArray(
36+
m_array = state->scene->createArray(
3737
desc.elementType, desc.numItems1, desc.numItems2, desc.numItems3);
3838
syncSharedData();
3939
}

tsd/src/anari_tsd/CMakeLists.txt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
## Copyright 2026 NVIDIA Corporation
22
## SPDX-License-Identifier: Apache-2.0
33

4-
project(anari_library_tsd LANGUAGES CXX)
4+
project(tsd_device LANGUAGES CXX)
55

6-
project_add_library(SHARED
6+
project_add_library(OBJECT
77
Array.cpp
88
Device.cpp
99
DeviceGlobalState.cpp
@@ -14,25 +14,27 @@ project_add_library(SHARED
1414
Object.cpp
1515
World.cpp
1616
)
17-
project_link_libraries(PRIVATE tsd_app tsd_io anari::helium)
18-
project_compile_definitions(PRIVATE "anari_library_tsd_EXPORTS")
17+
project_link_libraries(PUBLIC tsd_app tsd_io anari::helium)
1918
project_include_directories(
20-
PRIVATE
19+
PUBLIC
20+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
2121
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
2222
)
2323

24-
## Generated code ##
25-
26-
include(GenerateExportHeader)
27-
generate_export_header(${PROJECT_NAME} EXPORT_MACRO_NAME "ANARI_TSD_EXPORT")
28-
2924
anari_generate_queries(
3025
DEVICE_TARGET ${PROJECT_NAME}
3126
CPP_NAMESPACE tsd_device
3227
JSON_DEFINITIONS_FILE ${ANARI_CODE_GEN_ROOT}/devices/experimental_device.json
3328
)
3429

35-
## Install ##
30+
include(GenerateExportHeader)
31+
generate_export_header(${PROJECT_NAME} EXPORT_MACRO_NAME "ANARI_TSD_EXPORT")
32+
33+
## Installable TSD device library ##
34+
35+
project(anari_library_tsd LANGUAGES CXX)
36+
project_add_library(SHARED)
37+
project_link_libraries(PUBLIC tsd_device)
3638

3739
install(TARGETS ${PROJECT_NAME}
3840
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

0 commit comments

Comments
 (0)