Skip to content

Commit

Permalink
[js] Improve GPU JS feature
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Mar 25, 2024
1 parent 19cf03b commit cdcf659
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 202 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Checks: '-*,performance-*'
Checks: '-*,performance-*,clang-*'
CheckOptions:
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.ClassCase, value: lower_case }
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ if(SCORE_MACOS_ONLY_SYSTEM_LIBARIES)
endforeach()
endif()

set(CMAKE_SYSTEM_PREFIX_PATH "${CMAKE_SYSTEM_PREFIX_PATH}" CACHE INTERNAL "" FORCE)
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" CACHE INTERNAL "" FORCE)
# set(CMAKE_SYSTEM_PREFIX_PATH "${CMAKE_SYSTEM_PREFIX_PATH}" CACHE INTERNAL "" FORCE)
# set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" CACHE INTERNAL "" FORCE)

# QT_PREFIX: Qt5 / Qt6
list(GET QT_VERSION 0 QT_PREFIX)
Expand Down
29 changes: 29 additions & 0 deletions src/plugins/score-plugin-gfx/Gfx/GfxExecNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,33 @@ void gfx_exec_node::run(
out_ctl->port->write_value(std::move(out_ctl->value), 0);
}
}

void con_unvalidated::operator()(const ossia::value& val)
{
struct control_updater
{
std::shared_ptr<gfx_exec_node::control> ctrl;
ossia::value v;

void operator()() noexcept
{
ctrl->value = std::move(v);
ctrl->changed = true;
}
};

if(auto node = weak_node.lock())
{
// Check for the case where the node controls have changed
// due to the script changing
if(script_index != node->script_index)
return;

// This can happen if we sent controls from the UI before the execution engine had the time to add them
// Note: ideally something should be fixed to make that fit with the case above
if(i >= node->controls.size())
return;
ctx.executionQueue.enqueue(control_updater{node->controls[i], val});
}
}
}
31 changes: 2 additions & 29 deletions src/plugins/score-plugin-gfx/Gfx/GfxExecNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,40 +102,13 @@ class SCORE_PLUGIN_GFX_EXPORT gfx_exec_node : public ossia::graph_node
void run(const ossia::token_request& tk, ossia::exec_state_facade) noexcept override;
};

struct control_updater
{
std::shared_ptr<gfx_exec_node::control> ctrl;
ossia::value v;

void operator()() noexcept
{
ctrl->value = std::move(v);
ctrl->changed = true;
}
};

struct con_unvalidated
struct SCORE_PLUGIN_GFX_EXPORT con_unvalidated
{
const Execution::Context& ctx;
const std::size_t i;
const int32_t script_index{};
std::weak_ptr<gfx_exec_node> weak_node;
void operator()(const ossia::value& val)
{
if(auto node = weak_node.lock())
{
// Check for the case where the node controls have changed
// due to the script changing
if(script_index != node->script_index)
return;

// This can happen if we sent controls from the UI before the execution engine had the time to add them
// Note: ideally something should be fixed to make that fit with the case above
if(i >= node->controls.size())
return;
ctx.executionQueue.enqueue(control_updater{node->controls[i], val});
}
}
void operator()(const ossia::value& val);
};

}
84 changes: 50 additions & 34 deletions src/plugins/score-plugin-js/JS/Executor/Component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ Component::on_gpuScriptChange(const QString& script, Execution::Transaction& com
// 1. Create new inlet & outlet arrays
ossia::inlets inls;
ossia::outlets outls;
Gfx::exec_controls controls;
std::vector<Execution::ExecutionCommand> controlSetups;

int inlet_idx = 0;
int outlet_idx = 0;
std::size_t control_index = 0;
{
const Execution::Context& ctx = system();
std::vector<std::shared_ptr<Gfx::gfx_exec_node::control>> controls;
if(auto object = process().currentObject())
{
for(auto n : object->children())
Expand All @@ -181,7 +181,7 @@ Component::on_gpuScriptChange(const QString& script, Execution::Transaction& com
control_index++;
}

else if(auto ctrl_in = qobject_cast<JS::ControlInlet*>(val_in))
else if(auto ctrl_in = qobject_cast<JS::ControlInlet*>(inlet))
{
auto inletport = new ossia::value_inlet;
auto control = std::make_shared<Gfx::gfx_exec_node::control>();
Expand All @@ -195,12 +195,18 @@ Component::on_gpuScriptChange(const QString& script, Execution::Transaction& com

model_ctrl->setupExecution(*inletport);
control->value = model_ctrl->value();
control->changed = true;

// TODO assert that we aren't going to connect twice
QObject::disconnect(model_ctrl, nullptr, this, nullptr);
QObject::connect(
model_ctrl, &Process::ControlInlet::valueChanged, this,
Gfx::con_unvalidated{ctx, control_index, script_index, weak_node});

// FIXME initial control state
// controlSetups.push_back([/* node, val = ctrl->value(), idx */] {
// // node->setControl(idx, val.apply(ossia::qt::ossia_to_qvariant{}));
// });
}

controls.push_back(control);
Expand Down Expand Up @@ -281,7 +287,7 @@ Component::on_gpuScriptChange(const QString& script, Execution::Transaction& com
}
*/

if(auto tex_out = qobject_cast<TextureOutlet*>(outlet))
else if(auto tex_out = qobject_cast<TextureOutlet*>(outlet))
{
outls.push_back(new ossia::texture_outlet);
}
Expand All @@ -297,14 +303,17 @@ Component::on_gpuScriptChange(const QString& script, Execution::Transaction& com
// Send the updates to the node
auto recable = std::shared_ptr<ossia::recabler>(
new ossia::recabler{node, system().execGraph, inls, outls});
commands.push_back([node, script, recable]() mutable {
commands.push_back([node, script, controls, recable]() mutable {
using namespace std;
// Note: we need to do this because we try to keep the Javascript node around
// because it's slow to recreate.
// But this causes a lot of problems, it'd be better to do like e.g. the faust
// process and entirely recreate a new node, + call update node.
(*recable)();

node->setScript(std::move(script));

swap(node->controls, controls);
});

SCORE_ASSERT(process().inlets().size() == inls.size());
Expand All @@ -330,50 +339,57 @@ Component::on_cpuScriptChange(const QString& script, Execution::Transaction& com
if(auto object = process().currentObject())
{
int idx = 0;
auto process_if_control
= [this, idx, &node, &controlSetups](ossia::value_port& vp) {
if(auto ctrl = qobject_cast<Process::ControlInlet*>(process().inlets()[idx]))
{
vp.type = ctrl->value().get_type();
vp.domain = ctrl->domain().get();

disconnect(ctrl, nullptr, this, nullptr);
if(auto impulse = qobject_cast<Process::ImpulseButton*>(ctrl))
{
connect(
ctrl, &Process::ControlInlet::valueChanged, this,
[this, node, idx](const ossia::value& val) {
this->in_exec([node, idx] { node->impulse(idx); });
});
}
else
{
// Common case
connect(
ctrl, &Process::ControlInlet::valueChanged, this,
[this, node, idx](const ossia::value& val) {
this->in_exec([node, val, idx] {
node->setControl(idx, val.apply(ossia::qt::ossia_to_qvariant{}));
});
});
controlSetups.push_back([node, val = ctrl->value(), idx] {
node->setControl(idx, val.apply(ossia::qt::ossia_to_qvariant{}));
});
}
}
};
for(auto n : object->children())
{
if(auto ctrl_in = qobject_cast<ControlInlet*>(n))
{
inls.push_back(new ossia::value_inlet);
inls.back()->target<ossia::value_port>()->is_event = false;
auto& vp = *inls.back()->target<ossia::value_port>();
vp.is_event = false;

process_if_control(vp);

++idx;
}
else if(auto val_in = qobject_cast<ValueInlet*>(n))
{
inls.push_back(new ossia::value_inlet);
auto& vp = *inls.back()->target<ossia::value_port>();

vp.is_event = !val_in->isEvent();
if(auto ctrl = qobject_cast<Process::ControlInlet*>(process().inlets()[idx]))
{
vp.type = ctrl->value().get_type();
vp.domain = ctrl->domain().get();

disconnect(ctrl, nullptr, this, nullptr);
if(auto impulse = qobject_cast<Process::ImpulseButton*>(ctrl))
{
connect(
ctrl, &Process::ControlInlet::valueChanged, this,
[this, node, idx](const ossia::value& val) {
this->in_exec([node, idx] { node->impulse(idx); });
});
}
else
{
// Common case
connect(
ctrl, &Process::ControlInlet::valueChanged, this,
[this, node, idx](const ossia::value& val) {
this->in_exec([node, val, idx] {
node->setControl(idx, val.apply(ossia::qt::ossia_to_qvariant{}));
});
});
controlSetups.push_back([node, val = ctrl->value(), idx] {
node->setControl(idx, val.apply(ossia::qt::ossia_to_qvariant{}));
});
}
}
process_if_control(vp);

++idx;
}
Expand Down
Loading

0 comments on commit cdcf659

Please sign in to comment.