New ("fullframe") CPU compositor backend is being used now, and all the code
related to "tiled" CPU compositor is just never used anymore. The new backend
is faster, uses less memory, better matches GPU compositor, etc.
TL;DR: 20 thousand lines of code gone.
This commit:
- Removes various bits and pieces related to "tiled" compositor (execution
groups, one-pixel-at-a-time node processing, read/write buffer operations
related to node execution groups).
- "GPU" (OpenCL) execution device, that was only used by several nodes of
the tiled compositor.
- With that, remove CLEW external library too, since nothing within Blender
uses OpenCL directly anymore.
Pull Request: https://projects.blender.org/blender/blender/pulls/118819
175 lines
5.6 KiB
C++
175 lines
5.6 KiB
C++
/* SPDX-FileCopyrightText: 2021 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "BLI_map.hh"
|
|
#include "BLI_set.hh"
|
|
|
|
#include "COM_ConstantFolder.h"
|
|
#include "COM_NodeOperationBuilder.h"
|
|
#include "COM_SetColorOperation.h"
|
|
#include "COM_SetValueOperation.h"
|
|
#include "COM_SetVectorOperation.h"
|
|
#include "COM_WorkScheduler.h"
|
|
|
|
namespace blender::compositor {
|
|
|
|
ConstantFolder::ConstantFolder(NodeOperationBuilder &operations_builder)
|
|
: operations_builder_(operations_builder)
|
|
{
|
|
BLI_rcti_init(&max_area_, INT_MIN, INT_MAX, INT_MIN, INT_MAX);
|
|
BLI_rcti_init(&first_elem_area_, 0, 1, 0, 1);
|
|
}
|
|
|
|
static bool is_constant_foldable(NodeOperation *operation)
|
|
{
|
|
if (operation->get_flags().can_be_constant && !operation->get_flags().is_constant_operation) {
|
|
for (int i = 0; i < operation->get_number_of_input_sockets(); i++) {
|
|
NodeOperation *input = operation->get_input_operation(i);
|
|
if (!input->get_flags().is_constant_operation ||
|
|
!static_cast<ConstantOperation *>(input)->can_get_constant_elem())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static Set<NodeOperation *> find_constant_foldable_operations(Span<NodeOperation *> operations)
|
|
{
|
|
Set<NodeOperation *> foldable_ops;
|
|
for (NodeOperation *op : operations) {
|
|
if (is_constant_foldable(op)) {
|
|
foldable_ops.add(op);
|
|
}
|
|
}
|
|
return foldable_ops;
|
|
}
|
|
|
|
static ConstantOperation *create_constant_operation(DataType data_type, const float *constant_elem)
|
|
{
|
|
switch (data_type) {
|
|
case DataType::Color: {
|
|
SetColorOperation *color_op = new SetColorOperation();
|
|
color_op->set_channels(constant_elem);
|
|
return color_op;
|
|
}
|
|
case DataType::Vector: {
|
|
SetVectorOperation *vector_op = new SetVectorOperation();
|
|
vector_op->set_vector(constant_elem);
|
|
return vector_op;
|
|
}
|
|
case DataType::Value: {
|
|
SetValueOperation *value_op = new SetValueOperation();
|
|
value_op->set_value(*constant_elem);
|
|
return value_op;
|
|
}
|
|
default: {
|
|
BLI_assert_msg(0, "Non implemented data type");
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
ConstantOperation *ConstantFolder::fold_operation(NodeOperation *operation)
|
|
{
|
|
const DataType data_type = operation->get_output_socket()->get_data_type();
|
|
MemoryBuffer fold_buf(data_type, first_elem_area_);
|
|
Vector<MemoryBuffer *> input_bufs = get_constant_input_buffers(operation);
|
|
operation->init_data();
|
|
operation->render(&fold_buf, {first_elem_area_}, input_bufs);
|
|
|
|
MemoryBuffer *constant_buf = create_constant_buffer(data_type);
|
|
constant_buf->copy_from(&fold_buf, first_elem_area_);
|
|
ConstantOperation *constant_op = create_constant_operation(data_type,
|
|
constant_buf->get_buffer());
|
|
operations_builder_.replace_operation_with_constant(operation, constant_op);
|
|
constant_buffers_.add_new(constant_op, constant_buf);
|
|
return constant_op;
|
|
}
|
|
|
|
MemoryBuffer *ConstantFolder::create_constant_buffer(const DataType data_type)
|
|
{
|
|
/* Create a single elem buffer with maximum area possible so readers can read any coordinate
|
|
* returning always same element. */
|
|
return new MemoryBuffer(data_type, max_area_, true);
|
|
}
|
|
|
|
Vector<MemoryBuffer *> ConstantFolder::get_constant_input_buffers(NodeOperation *operation)
|
|
{
|
|
const int num_inputs = operation->get_number_of_input_sockets();
|
|
Vector<MemoryBuffer *> inputs_bufs(num_inputs);
|
|
for (int i = 0; i < num_inputs; i++) {
|
|
BLI_assert(operation->get_input_operation(i)->get_flags().is_constant_operation);
|
|
ConstantOperation *constant_op = static_cast<ConstantOperation *>(
|
|
operation->get_input_operation(i));
|
|
MemoryBuffer *constant_buf = constant_buffers_.lookup_or_add_cb(constant_op, [=] {
|
|
MemoryBuffer *buf = create_constant_buffer(
|
|
constant_op->get_output_socket()->get_data_type());
|
|
constant_op->render(buf, {first_elem_area_}, {});
|
|
return buf;
|
|
});
|
|
inputs_bufs[i] = constant_buf;
|
|
}
|
|
return inputs_bufs;
|
|
}
|
|
|
|
Vector<ConstantOperation *> ConstantFolder::try_fold_operations(Span<NodeOperation *> operations)
|
|
{
|
|
Set<NodeOperation *> foldable_ops = find_constant_foldable_operations(operations);
|
|
if (foldable_ops.is_empty()) {
|
|
return Vector<ConstantOperation *>();
|
|
}
|
|
|
|
Vector<ConstantOperation *> new_folds;
|
|
for (NodeOperation *op : foldable_ops) {
|
|
ConstantOperation *constant_op = fold_operation(op);
|
|
new_folds.append(constant_op);
|
|
}
|
|
return new_folds;
|
|
}
|
|
|
|
int ConstantFolder::fold_operations()
|
|
{
|
|
WorkScheduler::start();
|
|
Vector<ConstantOperation *> last_folds = try_fold_operations(
|
|
operations_builder_.get_operations());
|
|
int folds_count = last_folds.size();
|
|
while (last_folds.size() > 0) {
|
|
Vector<NodeOperation *> ops_to_fold;
|
|
for (ConstantOperation *fold : last_folds) {
|
|
get_operation_output_operations(fold, ops_to_fold);
|
|
}
|
|
last_folds = try_fold_operations(ops_to_fold);
|
|
folds_count += last_folds.size();
|
|
}
|
|
WorkScheduler::stop();
|
|
|
|
delete_constant_buffers();
|
|
|
|
return folds_count;
|
|
}
|
|
|
|
void ConstantFolder::delete_constant_buffers()
|
|
{
|
|
for (MemoryBuffer *buf : constant_buffers_.values()) {
|
|
delete buf;
|
|
}
|
|
constant_buffers_.clear();
|
|
}
|
|
|
|
void ConstantFolder::get_operation_output_operations(NodeOperation *operation,
|
|
Vector<NodeOperation *> &r_outputs)
|
|
{
|
|
const Vector<NodeOperationBuilder::Link> &links = operations_builder_.get_links();
|
|
for (const NodeOperationBuilder::Link &link : links) {
|
|
if (&link.from()->get_operation() == operation) {
|
|
r_outputs.append(&link.to()->get_operation());
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace blender::compositor
|