[Bf-blender-cvs] [b17c4900431] compositor-full-frame: Compositor: Do constant folding for full frame execution
Manuel Castilla
noreply at git.blender.org
Mon May 31 11:31:51 CEST 2021
Commit: b17c49004318cd6e2ef8587a7defe498e1d97333
Author: Manuel Castilla
Date: Sun May 30 16:22:07 2021 +0200
Branches: compositor-full-frame
https://developer.blender.org/rBb17c49004318cd6e2ef8587a7defe498e1d97333
Compositor: Do constant folding for full frame execution
All operations with constant pixel/elements are evaluated into primitive Value/Vector/Color constant operations prior rendering execution. This is the case of operations that are constant only when all their inputs are so. Such operations should set can_be_constant flag to true. is_constant flag is only used for primitive operations (Color/Vector/Value) which are the only constant operations during rendering execution.
===================================================================
M source/blender/compositor/CMakeLists.txt
M source/blender/compositor/intern/COM_BufferOperation.cc
M source/blender/compositor/intern/COM_BufferOperation.h
A source/blender/compositor/intern/COM_ConstantFolder.cc
A source/blender/compositor/intern/COM_ConstantFolder.h
M source/blender/compositor/intern/COM_Debug.cc
M source/blender/compositor/intern/COM_Debug.h
M source/blender/compositor/intern/COM_ExecutionModel.cc
M source/blender/compositor/intern/COM_ExecutionModel.h
M source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
M source/blender/compositor/intern/COM_FullFrameExecutionModel.h
M source/blender/compositor/intern/COM_NodeOperation.cc
M source/blender/compositor/intern/COM_NodeOperation.h
M source/blender/compositor/intern/COM_TiledExecutionModel.cc
M source/blender/compositor/intern/COM_TiledExecutionModel.h
A source/blender/compositor/operations/COM_ConstantOperation.cc
A source/blender/compositor/operations/COM_ConstantOperation.h
M source/blender/compositor/operations/COM_SetColorOperation.h
M source/blender/compositor/operations/COM_SetValueOperation.h
M source/blender/compositor/operations/COM_SetVectorOperation.cc
M source/blender/compositor/operations/COM_SetVectorOperation.h
===================================================================
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index ad2ae064ec0..cdeb357df95 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -61,6 +61,8 @@ set(SRC
intern/COM_ChunkOrderHotspot.h
intern/COM_CompositorContext.cc
intern/COM_CompositorContext.h
+ intern/COM_ConstantFolder.cc
+ intern/COM_ConstantFolder.h
intern/COM_Converter.cc
intern/COM_Converter.h
intern/COM_Debug.cc
@@ -450,6 +452,8 @@ set(SRC
operations/COM_MixOperation.h
operations/COM_ReadBufferOperation.cc
operations/COM_ReadBufferOperation.h
+ operations/COM_ConstantOperation.cc
+ operations/COM_ConstantOperation.h
operations/COM_SetColorOperation.cc
operations/COM_SetColorOperation.h
operations/COM_SetValueOperation.cc
diff --git a/source/blender/compositor/intern/COM_BufferOperation.cc b/source/blender/compositor/intern/COM_BufferOperation.cc
index c1e64142443..561a754a500 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.cc
+++ b/source/blender/compositor/intern/COM_BufferOperation.cc
@@ -20,7 +20,7 @@
namespace blender::compositor {
-BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type) : NodeOperation()
+BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type) : ConstantOperation()
{
buffer_ = buffer;
/* TODO: Implement a MemoryBuffer get_size() method returning a Size2d type. Shorten following
@@ -30,6 +30,14 @@ BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type) : Nod
resolution[1] = buffer->getHeight();
setResolution(resolution);
addOutputSocket(data_type);
+
+ flags.is_constant_operation = buffer_->is_a_single_elem();
+}
+
+float *BufferOperation::get_constant_elem()
+{
+ BLI_assert(buffer_->is_a_single_elem());
+ return buffer_->getBuffer();
}
void *BufferOperation::initializeTileData(rcti * /*rect*/)
diff --git a/source/blender/compositor/intern/COM_BufferOperation.h b/source/blender/compositor/intern/COM_BufferOperation.h
index f87cd4db94e..2fa90b872ae 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.h
+++ b/source/blender/compositor/intern/COM_BufferOperation.h
@@ -18,17 +18,18 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
namespace blender::compositor {
-class BufferOperation : public NodeOperation {
+class BufferOperation : public ConstantOperation {
private:
MemoryBuffer *buffer_;
public:
BufferOperation(MemoryBuffer *buffer, DataType data_type);
+ float *get_constant_elem();
void *initializeTileData(rcti *rect) override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) override;
diff --git a/source/blender/compositor/intern/COM_ConstantFolder.cc b/source/blender/compositor/intern/COM_ConstantFolder.cc
new file mode 100644
index 00000000000..a2b13fc3563
--- /dev/null
+++ b/source/blender/compositor/intern/COM_ConstantFolder.cc
@@ -0,0 +1,232 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2011, Blender Foundation.
+ */
+
+#include "COM_ConstantFolder.h"
+#include "BLI_rect.h"
+#include "COM_ConstantOperation.h"
+#include "COM_SetColorOperation.h"
+#include "COM_SetValueOperation.h"
+#include "COM_SetVectorOperation.h"
+
+#include <limits>
+
+namespace blender::compositor {
+
+/**
+ * \param operations: Container of operations to fold. Folded operations will be replaced
+ * with constant operations.
+ * \param output_links_map: Operations output links. Folded operations links will be relinked to
+ * their constant operation result.
+ * \param exec_system: Execution system.
+ */
+ConstantFolder::ConstantFolder(Vector<NodeOperation *> &operations,
+ Map<NodeOperation *, Set<NodeOperation *>> &output_links,
+ ExecutionSystem &exec_system)
+ : all_operations_(operations), output_links_(output_links), exec_system_(exec_system)
+{
+ BLI_rcti_init(&max_area_,
+ std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::max(),
+ std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::max());
+ BLI_rcti_init(&first_elem_area_, 0, 1, 0, 1);
+}
+
+static bool is_constant_foldable(NodeOperation *op)
+{
+ if (!op->get_flags().can_be_constant || op->get_flags().is_constant_operation) {
+ return false;
+ }
+ for (int i = 0; i < op->getNumberOfInputSockets(); i++) {
+ if (!op->get_input_operation(i)->get_flags().is_constant_operation) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static Vector<NodeOperation *> find_constant_foldable_operations(Span<NodeOperation *> operations)
+{
+ Vector<NodeOperation *> foldable_ops;
+ for (NodeOperation *op : operations) {
+ if (is_constant_foldable(op)) {
+ foldable_ops.append(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->setChannels(constant_elem);
+ return color_op;
+ }
+ case DataType::Vector: {
+ SetVectorOperation *vector_op = new SetVectorOperation();
+ vector_op->setVector(constant_elem);
+ return vector_op;
+ }
+ case DataType::Value: {
+ SetValueOperation *value_op = new SetValueOperation();
+ value_op->setValue(*constant_elem);
+ return value_op;
+ }
+ default: {
+ BLI_assert(!"Non implemented data type");
+ return nullptr;
+ }
+ }
+}
+
+ConstantOperation *ConstantFolder::fold_operation(NodeOperation *op)
+{
+ const DataType data_type = op->getOutputSocket()->getDataType();
+ MemoryBuffer *fold_buf = create_constant_buffer(data_type);
+ Vector<MemoryBuffer *> inputs_bufs = get_constant_inputs_buffers(op);
+ op->render(fold_buf, {first_elem_area_}, inputs_bufs, exec_system_);
+
+ ConstantOperation *constant_op = create_constant_operation(data_type, fold_buf->get_elem(0, 0));
+ all_operations_.append(constant_op);
+ constants_buffers_.add_new(constant_op, fold_buf);
+ relink_operation_outputs_to_constant(op, constant_op);
+ remove_folded_operation(op);
+ return constant_op;
+}
+
+void ConstantFolder::relink_operation_outputs_to_constant(NodeOperation *from_op,
+ ConstantOperation *to_op)
+{
+ if (!output_links_.contains(from_op)) {
+ return;
+ }
+ Set<NodeOperation *> outputs = output_links_.pop(from_op);
+ for (NodeOperation *out : outputs) {
+ for (int i = 0; i < out->getNumberOfInputSockets(); i++) {
+ NodeOperationInput *socket = out->getInputSocket(i);
+ NodeOperationOutput *link = socket->getLink();
+ if (link && &link->getOperation() == from_op) {
+ socket->setLink(to_op->getOutputSocket());
+ /* TODO: As resolutions are determined before constant folding we need to manually set
+ * constant operations resolutions. Once tiled implementation is removed constant folding
+ * should be done first and this code can be removed. */
+ uint temp[2];
+ uint resolution[2] = {out->getWidth(), out->getHeight()};
+ to_op->getOutputSocket()->determineResolution(temp, resolution);
+ }
+ }
+ }
+ output_links_.add_new(to_op, std::move(outputs));
+}
+
+void ConstantFolder::remove_folded_operation(NodeOperation *op)
+{
+ output_links_.remove(op);
+ folded_operations_.add(op);
+ for (int i = 0; i < op->getNumberOfInputSockets(); i++) {
+ NodeOperation *input = op->get_input_operation(i);
+ BLI_assert(output_links_.contains(input));
+ Set<NodeOperation *> &input_outputs = output_links_.lookup(input);
+ input_outputs.remove(op);
+ if (input_outputs.size() == 0) {
+ output_links_.remove(input);
+ folded_operations_.add(input);
+ }
+ }
+}
+
+MemoryBuffer *ConstantFolder::create_constant_buffer(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_inputs_buffers(NodeOperation *op)
+{
+ const int num_inputs = op->getNumberOfInputSockets();
+ Vector<MemoryBuffer *> inputs_bufs(num_inputs);
+ for (int i = 0; i < num_inputs; i++) {
+ ConstantOperation *constant_op = static_cast<ConstantOperation *>(op->get_input_operation(i));
+ MemoryBuffer *constant_buf = constants_buffers_.lookup_or_add_cb(constant_op, [=] {
+ MemoryBuffer *buf = create_constant_buffer(constant_op->getOutputSocket()->getDataType());
+ constant_op->render(buf, {first_elem_area_}, {}, exec_system_);
+ return buf;
+ });
+ inputs_bufs[i] = constant_buf;
+ }
+ return inputs_bufs;
+}
+
+/** Returns constant operations resulted from folding. */
+Vector<ConstantOperation *> ConstantFolder::try_fold_operations(Span<NodeOperation *> operations)
+{
+ Vector<NodeOperation *> foldable_ops = find_constant_foldable_operations(operations);
+ if (foldable_ops.size() == 0) {
+ return Vector<ConstantOperation *>();
+ }
+ Vector<ConstantOperation *> new_folds;
+ for (NodeOperation *op : foldable_ops) {
+ ConstantOperation *constant_op = fold_operation(op);
+ new_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list