[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