Get the latest Blender, older versions, or experimental builds.
Stay up-to-date with the new features in the latest Blender releases.
Access production assets and knowledge from the open movies.
Documentation on the usage and features in Blender.
Latest development updates, by Blender developers.
Guidelines, release notes and development docs.
A platform to collect and share results of the Blender Benchmark.
The yearly event that brings the community together.
Support core development with a monthly contribution.
Perform a single donation with more payment options available.
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup fn
*
* This file contains common utilities for actually executing a lazy-function.
*/
#include "BLI_parameter_pack_utils.hh"
#include "FN_lazy_function.hh"
namespace blender::fn::lazy_function {
/**
* Most basic implementation of #Params. It does not actually implement any logic for how to
* retrieve inputs or set outputs. Instead, code using #BasicParams has to implement that.
class BasicParams : public Params {
private:
const Span<GMutablePointer> inputs_;
const Span<GMutablePointer> outputs_;
MutableSpan<std::optional<ValueUsage>> input_usages_;
Span<ValueUsage> output_usages_;
MutableSpan<bool> set_outputs_;
public:
BasicParams(const LazyFunction &fn,
const Span<GMutablePointer> inputs,
const Span<GMutablePointer> outputs,
MutableSpan<std::optional<ValueUsage>> input_usages,
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;
bool try_enable_multi_threading_impl() override;
};
namespace detail {
* Utility to implement #execute_lazy_function_eagerly.
template<typename... Inputs, typename... Outputs, size_t... InIndices, size_t... OutIndices>
inline void execute_lazy_function_eagerly_impl(
const LazyFunction &fn,
UserData *user_data,
LocalUserData *local_user_data,
std::tuple<Inputs...> &inputs,
std::tuple<Outputs *...> &outputs,
std::index_sequence<InIndices...> /* in_indices */,
std::index_sequence<OutIndices...> /* out_indices */)
{
constexpr size_t InputsNum = sizeof...(Inputs);
constexpr size_t OutputsNum = sizeof...(Outputs);
std::array<GMutablePointer, InputsNum> input_pointers;
std::array<GMutablePointer, OutputsNum> output_pointers;
std::array<std::optional<ValueUsage>, InputsNum> input_usages;
std::array<ValueUsage, OutputsNum> output_usages;
std::array<bool, OutputsNum> set_outputs;
(
[&]() {
constexpr size_t I = InIndices;
/* Use `typedef` instead of `using` to work around a compiler bug. */
typedef Inputs T;
const CPPType &type = CPPType::get<T>();
input_pointers[I] = {type, &std::get<I>(inputs)};
}(),
...);
constexpr size_t I = OutIndices;
typedef Outputs T;
output_pointers[I] = {type, std::get<I>(outputs)};
output_usages.fill(ValueUsage::Used);
set_outputs.fill(false);
LinearAllocator<> allocator;
Context context(fn.init_storage(allocator), user_data, local_user_data);
BasicParams params{
fn, input_pointers, output_pointers, input_usages, output_usages, set_outputs};
fn.execute(params, context);
fn.destruct_storage(context.storage);
/* Make sure all outputs have been computed. */
BLI_assert(!Span<bool>(set_outputs).contains(false));
}
} // namespace detail
* In some cases (mainly for tests), the set of inputs and outputs for a lazy-function is known at
* compile time and one just wants to compute the outputs based on the inputs, without any
* laziness.
* This function does exactly that. It takes all inputs in a tuple and writes the outputs to points
* provided in a second tuple. Since all inputs have to be provided, the lazy-function has to
* compute all outputs.
template<typename... Inputs, typename... Outputs>
inline void execute_lazy_function_eagerly(const LazyFunction &fn,
std::tuple<Inputs...> inputs,
std::tuple<Outputs *...> outputs)
BLI_assert(fn.inputs().size() == sizeof...(Inputs));
BLI_assert(fn.outputs().size() == sizeof...(Outputs));
detail::execute_lazy_function_eagerly_impl(fn,
user_data,
local_user_data,
inputs,
outputs,
std::make_index_sequence<sizeof...(Inputs)>(),
std::make_index_sequence<sizeof...(Outputs)>());
} // namespace blender::fn::lazy_function