WIP: Functions: process multiple elements at once in the lazy-function api #105697
|
@ -124,6 +124,8 @@ class Params {
|
|||
* The #LazyFunction must leave returned object in an initialized state, but can move from it.
|
||||
*/
|
||||
void *try_get_input_data_ptr(int index) const;
|
||||
void try_get_input_data_ptr(IndexRange indices, MutableSpan<void *> r_data) const;
|
||||
void try_get_input_data_ptr(Span<int> indices, MutableSpan<void *> r_data) const;
|
||||
|
||||
/**
|
||||
* Same as #try_get_input_data_ptr, but if the data is not yet available, request it. This makes
|
||||
|
@ -138,12 +140,16 @@ class Params {
|
|||
* After the output has been initialized to its final value, #output_set has to be called.
|
||||
*/
|
||||
void *get_output_data_ptr(int index);
|
||||
void get_output_data_ptr(IndexRange indices, MutableSpan<void *> r_data);
|
||||
void get_output_data_ptr(Span<int> indices, MutableSpan<void *> r_data);
|
||||
|
||||
/**
|
||||
* Call this after the output value is initialized. After this is called, the value must not be
|
||||
* touched anymore. It may be moved or destructed immediately.
|
||||
*/
|
||||
void output_set(int index);
|
||||
void output_set(IndexRange indices);
|
||||
void output_set(Span<int> indices);
|
||||
|
||||
/**
|
||||
* Allows the #LazyFunction to check whether an output was computed already without keeping
|
||||
|
@ -190,13 +196,16 @@ class Params {
|
|||
* methods above to make it easy to insert additional debugging logic on top of the
|
||||
* implementations.
|
||||
*/
|
||||
virtual void *try_get_input_data_ptr_impl(int index) const = 0;
|
||||
virtual void *try_get_input_data_ptr_or_request_impl(int index) = 0;
|
||||
virtual void *get_output_data_ptr_impl(int index) = 0;
|
||||
virtual void output_set_impl(int index) = 0;
|
||||
virtual bool output_was_set_impl(int index) const = 0;
|
||||
virtual ValueUsage get_output_usage_impl(int index) const = 0;
|
||||
virtual void set_input_unused_impl(int index) = 0;
|
||||
virtual void try_get_input_data_ptr_impl(Span<int> indices,
|
||||
MutableSpan<void *> r_data) const = 0;
|
||||
virtual void try_get_input_data_ptr_or_request_impl(Span<int> indices,
|
||||
MutableSpan<void *> r_data) = 0;
|
||||
virtual void get_output_data_ptr_impl(Span<int> indices, MutableSpan<void *> r_data) = 0;
|
||||
virtual void output_set_impl(Span<int> indices) = 0;
|
||||
virtual void output_was_set_impl(Span<int> indices, MutableSpan<bool> r_result) const = 0;
|
||||
virtual void get_output_usage_impl(Span<int> indices,
|
||||
MutableSpan<ValueUsage> r_result) const = 0;
|
||||
virtual void set_input_unused_impl(Span<int> indices) = 0;
|
||||
virtual bool try_enable_multi_threading_impl();
|
||||
};
|
||||
|
||||
|
@ -365,43 +374,99 @@ inline Params::Params(const LazyFunction &fn,
|
|||
{
|
||||
}
|
||||
|
||||
inline Array<int, 16> get_indices_array(const IndexRange indices)
|
||||
{
|
||||
Array<int, 16> indices_array(indices.size());
|
||||
for (const int i : IndexRange(indices.size())) {
|
||||
indices_array[i] = indices[i];
|
||||
}
|
||||
return indices_array;
|
||||
}
|
||||
|
||||
inline void *Params::try_get_input_data_ptr(const int index) const
|
||||
{
|
||||
return this->try_get_input_data_ptr_impl(index);
|
||||
void *data;
|
||||
this->try_get_input_data_ptr_impl({index}, {&data, 1});
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void Params::get_output_data_ptr(const IndexRange indices, MutableSpan<void *> r_data)
|
||||
{
|
||||
Array<int, 16> indices_array = get_indices_array(indices);
|
||||
this->get_output_data_ptr(indices_array, r_data);
|
||||
}
|
||||
|
||||
inline void Params::get_output_data_ptr(const Span<int> indices, MutableSpan<void *> r_data)
|
||||
{
|
||||
BLI_assert(indices.size() == r_data.size());
|
||||
this->get_output_data_ptr_impl(indices, r_data);
|
||||
}
|
||||
|
||||
inline void Params::output_set(const IndexRange indices)
|
||||
{
|
||||
Array<int, 16> indices_array = get_indices_array(indices);
|
||||
this->output_set(indices_array);
|
||||
}
|
||||
|
||||
inline void Params::output_set(const Span<int> indices)
|
||||
{
|
||||
this->output_set_impl(indices);
|
||||
}
|
||||
|
||||
inline void Params::try_get_input_data_ptr(const IndexRange indices,
|
||||
MutableSpan<void *> r_data) const
|
||||
{
|
||||
Array<int, 16> indices_array = get_indices_array(indices);
|
||||
this->try_get_input_data_ptr(indices_array, r_data);
|
||||
}
|
||||
|
||||
inline void Params::try_get_input_data_ptr(const Span<int> indices,
|
||||
MutableSpan<void *> r_data) const
|
||||
{
|
||||
BLI_assert(indices.size() == r_data.size());
|
||||
this->try_get_input_data_ptr_impl(indices, r_data);
|
||||
}
|
||||
|
||||
inline void *Params::try_get_input_data_ptr_or_request(const int index)
|
||||
{
|
||||
this->assert_valid_thread();
|
||||
return this->try_get_input_data_ptr_or_request_impl(index);
|
||||
void *data;
|
||||
this->try_get_input_data_ptr_or_request_impl({index}, {&data, 1});
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void *Params::get_output_data_ptr(const int index)
|
||||
{
|
||||
this->assert_valid_thread();
|
||||
return this->get_output_data_ptr_impl(index);
|
||||
void *data;
|
||||
this->get_output_data_ptr_impl({index}, {&data, 1});
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void Params::output_set(const int index)
|
||||
{
|
||||
this->assert_valid_thread();
|
||||
this->output_set_impl(index);
|
||||
this->output_set_impl({index});
|
||||
}
|
||||
|
||||
inline bool Params::output_was_set(const int index) const
|
||||
{
|
||||
return this->output_was_set_impl(index);
|
||||
bool result;
|
||||
this->output_was_set_impl({index}, {&result, 1});
|
||||
return result;
|
||||
}
|
||||
|
||||
inline ValueUsage Params::get_output_usage(const int index) const
|
||||
{
|
||||
return this->get_output_usage_impl(index);
|
||||
ValueUsage result;
|
||||
this->get_output_usage_impl({index}, {&result, 1});
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void Params::set_input_unused(const int index)
|
||||
{
|
||||
this->assert_valid_thread();
|
||||
this->set_input_unused_impl(index);
|
||||
this->set_input_unused_impl({index});
|
||||
}
|
||||
|
||||
template<typename T> inline T Params::extract_input(const int index)
|
||||
|
|
|
@ -34,13 +34,15 @@ class BasicParams : public Params {
|
|||
Span<ValueUsage> output_usages,
|
||||
MutableSpan<bool> set_outputs);
|
||||
|
||||
void *try_get_input_data_ptr_impl(const int index) const override;
|
||||
void *try_get_input_data_ptr_or_request_impl(const int index) override;
|
||||
void *get_output_data_ptr_impl(const int index) override;
|
||||
void output_set_impl(const int index) override;
|
||||
bool output_was_set_impl(const int index) const override;
|
||||
ValueUsage get_output_usage_impl(const int index) const override;
|
||||
void set_input_unused_impl(const int index) override;
|
||||
void try_get_input_data_ptr_impl(Span<int> indices, MutableSpan<void *> r_data) const override;
|
||||
void try_get_input_data_ptr_or_request_impl(Span<int> indices,
|
||||
MutableSpan<void *> r_data) override;
|
||||
void get_output_data_ptr_impl(Span<int> indices, MutableSpan<void *> r_data) override;
|
||||
void output_set_impl(Span<int> indices) override;
|
||||
void output_was_set_impl(Span<int> indices, MutableSpan<bool> r_result) const override;
|
||||
void get_output_usage_impl(const Span<int> indices,
|
||||
MutableSpan<ValueUsage> r_result) const override;
|
||||
void set_input_unused_impl(Span<int> indices) override;
|
||||
bool try_enable_multi_threading_impl() override;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,43 +23,65 @@ BasicParams::BasicParams(const LazyFunction &fn,
|
|||
{
|
||||
}
|
||||
|
||||
void *BasicParams::try_get_input_data_ptr_impl(const int index) const
|
||||
void BasicParams::try_get_input_data_ptr_impl(const Span<int> indices,
|
||||
MutableSpan<void *> r_data) const
|
||||
{
|
||||
return inputs_[index].get();
|
||||
}
|
||||
|
||||
void *BasicParams::try_get_input_data_ptr_or_request_impl(const int index)
|
||||
{
|
||||
void *value = inputs_[index].get();
|
||||
if (value == nullptr) {
|
||||
input_usages_[index] = ValueUsage::Used;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
r_data[i] = inputs_[index].get();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void *BasicParams::get_output_data_ptr_impl(const int index)
|
||||
void BasicParams::try_get_input_data_ptr_or_request_impl(const Span<int> indices,
|
||||
MutableSpan<void *> r_data)
|
||||
{
|
||||
return outputs_[index].get();
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
void *value = inputs_[index].get();
|
||||
if (value == nullptr) {
|
||||
input_usages_[index] = ValueUsage::Used;
|
||||
}
|
||||
r_data[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParams::output_set_impl(const int index)
|
||||
void BasicParams::get_output_data_ptr_impl(const Span<int> indices, MutableSpan<void *> r_data)
|
||||
{
|
||||
set_outputs_[index] = true;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
r_data[i] = outputs_[index].get();
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParams::output_was_set_impl(const int index) const
|
||||
void BasicParams::output_set_impl(const Span<int> indices)
|
||||
{
|
||||
return set_outputs_[index];
|
||||
for (const int index : indices) {
|
||||
set_outputs_[index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
ValueUsage BasicParams::get_output_usage_impl(const int index) const
|
||||
void BasicParams::output_was_set_impl(const Span<int> indices, MutableSpan<bool> r_result) const
|
||||
{
|
||||
return output_usages_[index];
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
r_result[i] = set_outputs_[index];
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParams::set_input_unused_impl(const int index)
|
||||
void BasicParams::get_output_usage_impl(const Span<int> indices,
|
||||
MutableSpan<ValueUsage> r_result) const
|
||||
{
|
||||
input_usages_[index] = ValueUsage::Unused;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
r_result[i] = output_usages_[index];
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParams::set_input_unused_impl(const Span<int> indices)
|
||||
{
|
||||
for (const int index : indices) {
|
||||
input_usages_[index] = ValueUsage::Unused;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParams::try_enable_multi_threading_impl()
|
||||
|
|
|
@ -1223,63 +1223,90 @@ class GraphExecutorLFParams final : public Params {
|
|||
}
|
||||
|
||||
private:
|
||||
void *try_get_input_data_ptr_impl(const int index) const override
|
||||
void try_get_input_data_ptr_impl(const Span<int> indices,
|
||||
MutableSpan<void *> r_data) const override
|
||||
{
|
||||
const InputState &input_state = node_state_.inputs[index];
|
||||
if (input_state.was_ready_for_execution) {
|
||||
return input_state.value;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
const InputState &input_state = node_state_.inputs[index];
|
||||
if (input_state.was_ready_for_execution) {
|
||||
r_data[i] = input_state.value;
|
||||
}
|
||||
else {
|
||||
r_data[i] = nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *try_get_input_data_ptr_or_request_impl(const int index) override
|
||||
void try_get_input_data_ptr_or_request_impl(const Span<int> indices,
|
||||
MutableSpan<void *> r_data) override
|
||||
{
|
||||
const InputState &input_state = node_state_.inputs[index];
|
||||
if (input_state.was_ready_for_execution) {
|
||||
return input_state.value;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
const InputState &input_state = node_state_.inputs[index];
|
||||
if (input_state.was_ready_for_execution) {
|
||||
r_data[i] = input_state.value;
|
||||
}
|
||||
else {
|
||||
r_data[i] = executor_.set_input_required_during_execution(
|
||||
node_, node_state_, index, current_task_);
|
||||
}
|
||||
}
|
||||
return executor_.set_input_required_during_execution(node_, node_state_, index, current_task_);
|
||||
}
|
||||
|
||||
void *get_output_data_ptr_impl(const int index) override
|
||||
void get_output_data_ptr_impl(const Span<int> indices, MutableSpan<void *> r_data) override
|
||||
{
|
||||
OutputState &output_state = node_state_.outputs[index];
|
||||
BLI_assert(!output_state.has_been_computed);
|
||||
if (output_state.value == nullptr) {
|
||||
LinearAllocator<> &allocator = executor_.get_main_or_local_allocator();
|
||||
const CPPType &type = node_.output(index).type();
|
||||
output_state.value = allocator.allocate(type.size(), type.alignment());
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
OutputState &output_state = node_state_.outputs[index];
|
||||
BLI_assert(!output_state.has_been_computed);
|
||||
if (output_state.value == nullptr) {
|
||||
LinearAllocator<> &allocator = executor_.get_main_or_local_allocator();
|
||||
const CPPType &type = node_.output(index).type();
|
||||
output_state.value = allocator.allocate(type.size(), type.alignment());
|
||||
}
|
||||
r_data[i] = output_state.value;
|
||||
}
|
||||
return output_state.value;
|
||||
}
|
||||
|
||||
void output_set_impl(const int index) override
|
||||
void output_set_impl(const Span<int> indices) override
|
||||
{
|
||||
OutputState &output_state = node_state_.outputs[index];
|
||||
BLI_assert(!output_state.has_been_computed);
|
||||
BLI_assert(output_state.value != nullptr);
|
||||
const OutputSocket &output_socket = node_.output(index);
|
||||
executor_.forward_value_to_linked_inputs(
|
||||
output_socket, {output_socket.type(), output_state.value}, current_task_);
|
||||
output_state.value = nullptr;
|
||||
output_state.has_been_computed = true;
|
||||
for (const int index : indices) {
|
||||
OutputState &output_state = node_state_.outputs[index];
|
||||
BLI_assert(!output_state.has_been_computed);
|
||||
BLI_assert(output_state.value != nullptr);
|
||||
const OutputSocket &output_socket = node_.output(index);
|
||||
executor_.forward_value_to_linked_inputs(
|
||||
output_socket, {output_socket.type(), output_state.value}, current_task_);
|
||||
output_state.value = nullptr;
|
||||
output_state.has_been_computed = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool output_was_set_impl(const int index) const override
|
||||
void output_was_set_impl(const Span<int> indices, MutableSpan<bool> r_result) const override
|
||||
{
|
||||
const OutputState &output_state = node_state_.outputs[index];
|
||||
return output_state.has_been_computed;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
const OutputState &output_state = node_state_.outputs[index];
|
||||
r_result[i] = output_state.has_been_computed;
|
||||
}
|
||||
}
|
||||
|
||||
ValueUsage get_output_usage_impl(const int index) const override
|
||||
void get_output_usage_impl(const Span<int> indices,
|
||||
MutableSpan<ValueUsage> r_result) const override
|
||||
{
|
||||
const OutputState &output_state = node_state_.outputs[index];
|
||||
return output_state.usage_for_execution;
|
||||
for (const int i : indices.index_range()) {
|
||||
const int index = indices[i];
|
||||
const OutputState &output_state = node_state_.outputs[index];
|
||||
r_result[i] = output_state.usage_for_execution;
|
||||
}
|
||||
}
|
||||
|
||||
void set_input_unused_impl(const int index) override
|
||||
void set_input_unused_impl(const Span<int> indices) override
|
||||
{
|
||||
executor_.set_input_unused_during_execution(node_, node_state_, index, current_task_);
|
||||
for (const int index : indices) {
|
||||
executor_.set_input_unused_during_execution(node_, node_state_, index, current_task_);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_enable_multi_threading_impl() override
|
||||
|
|
|
@ -521,19 +521,13 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
|
|||
|
||||
void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override
|
||||
{
|
||||
Vector<const void *> input_values(inputs_.size());
|
||||
Vector<void *> input_values(inputs_.size());
|
||||
Vector<void *> output_values(outputs_.size());
|
||||
for (const int i : inputs_.index_range()) {
|
||||
input_values[i] = params.try_get_input_data_ptr(i);
|
||||
}
|
||||
for (const int i : outputs_.index_range()) {
|
||||
output_values[i] = params.get_output_data_ptr(i);
|
||||
}
|
||||
params.try_get_input_data_ptr(inputs_.index_range(), input_values);
|
||||
params.get_output_data_ptr(outputs_.index_range(), output_values);
|
||||
execute_multi_function_on_value_or_field(
|
||||
*fn_item_.fn, fn_item_.owned_fn, input_types_, output_types_, input_values, output_values);
|
||||
for (const int i : outputs_.index_range()) {
|
||||
params.output_set(i);
|
||||
}
|
||||
params.output_set(outputs_.index_range());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue