[Bf-blender-cvs] [d81dd5a2681] compositor-full-frame: Compositor: Crop operations canvases to rendered areas

Manuel Castilla noreply at git.blender.org
Mon May 31 11:31:51 CEST 2021


Commit: d81dd5a2681028e32e659862599da6d32148d330
Author: Manuel Castilla
Date:   Sun May 30 16:59:39 2021 +0200
Branches: compositor-full-frame
https://developer.blender.org/rBd81dd5a2681028e32e659862599da6d32148d330

Compositor: Crop operations canvases to rendered areas

When calculating operations resolutions (canvas size), rendered areas are not known yet so worst case scenario is assumed which is full size. But they can be cropped to rendered areas bounds one they are known. This reduces memory usage as buffers size will be the same than rendered areas bounds.

===================================================================

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_SharedOperationBuffers.cc
M	source/blender/compositor/intern/COM_SharedOperationBuffers.h

===================================================================

diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
index e23e2f7bdca..9d0d4ab4883 100644
--- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
@@ -80,6 +80,8 @@ void FullFrameExecutionModel::execute(ExecutionSystem &exec_system)
   DebugInfo::graphviz(&exec_system, "compositor_after_folding");
 
   determine_areas_to_render_and_reads();
+  clamp_operations_to_rendered_areas();
+  DebugInfo::graphviz(&exec_system, "compositor_after_clamping");
   render_operations(exec_system);
 }
 
@@ -101,6 +103,14 @@ void FullFrameExecutionModel::determine_areas_to_render_and_reads()
   }
 }
 
+void FullFrameExecutionModel::clamp_operations_to_rendered_areas()
+{
+  for (NodeOperation *op : operations_) {
+    rcti bounds = active_buffers_.get_render_bounds(op);
+    op->set_canvas_area(bounds);
+  }
+}
+
 void FullFrameExecutionModel::ensure_inputs_rendered(NodeOperation *op,
                                                      ExecutionSystem &exec_system)
 {
@@ -126,12 +136,9 @@ Vector<MemoryBuffer *> FullFrameExecutionModel::get_input_buffers(NodeOperation
 
 MemoryBuffer *FullFrameExecutionModel::create_operation_buffer(NodeOperation *op)
 {
-  rcti op_rect;
-  BLI_rcti_init(&op_rect, 0, op->getWidth(), 0, op->getHeight());
-
   const DataType data_type = op->getOutputSocket(0)->getDataType();
   const bool is_a_single_elem = op->get_flags().is_constant_operation;
-  return new MemoryBuffer(data_type, op_rect, is_a_single_elem);
+  return new MemoryBuffer(data_type, op->get_canvas_area(), is_a_single_elem);
 }
 
 void FullFrameExecutionModel::render_operation(NodeOperation *op, ExecutionSystem &exec_system)
@@ -187,8 +194,8 @@ void FullFrameExecutionModel::determine_areas_to_render(NodeOperation *operation
   const int num_inputs = operation->getNumberOfInputSockets();
   for (int i = 0; i < num_inputs; i++) {
     NodeOperation *input_op = operation->get_input_operation(i);
-    rcti input_op_rect, input_area;
-    BLI_rcti_init(&input_op_rect, 0, input_op->getWidth(), 0, input_op->getHeight());
+    rcti input_op_rect = input_op->get_canvas_area();
+    rcti input_area;
     operation->get_area_of_interest(input_op, render_area, input_area);
 
     /* Ensure area of interest is within operation bounds. */
diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
index 0eb7accb114..4255cb217d1 100644
--- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
+++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
@@ -74,6 +74,7 @@ class FullFrameExecutionModel : public ExecutionModel {
 
  private:
   void determine_areas_to_render_and_reads();
+  void clamp_operations_to_rendered_areas();
   void render_operations(ExecutionSystem &exec_system);
 
   void ensure_inputs_rendered(NodeOperation *op, ExecutionSystem &exec_system);
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc
index b1ad0795e0c..c52fca81b12 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cc
+++ b/source/blender/compositor/intern/COM_NodeOperation.cc
@@ -38,9 +38,32 @@ NodeOperation::NodeOperation()
   this->m_resolutionInputSocketIndex = 0;
   this->m_width = 0;
   this->m_height = 0;
+  offset_x_ = 0;
+  offset_y_ = 0;
   this->m_btree = nullptr;
 }
 
+/**
+ * Get operation canvas area within whole compositing canvas.
+ */
+rcti NodeOperation::get_canvas_area() const
+{
+  rcti rect;
+  BLI_rcti_init(&rect, offset_x_, offset_x_ + m_width, offset_y_, offset_y_ + m_height);
+  return rect;
+}
+
+/**
+ * Set operation canvas area within whole compositing canvas.
+ */
+void NodeOperation::set_canvas_area(const rcti &rect)
+{
+  offset_x_ = rect.xmin;
+  offset_y_ = rect.ymin;
+  m_width = BLI_rcti_size_x(&rect);
+  m_height = BLI_rcti_size_y(&rect);
+}
+
 NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index)
 {
   return &m_outputs[index];
@@ -269,8 +292,10 @@ void NodeOperation::render_full_frame_fallback(MemoryBuffer *output_buf,
   initExecution();
   const bool is_output_operation = getNumberOfOutputSockets() == 0;
   if (!is_output_operation && output_buf->is_a_single_elem()) {
-    float *output_elem = output_buf->get_elem(0, 0);
-    readSampled(output_elem, 0, 0, PixelSampler::Nearest);
+    int x = areas[0].xmin;
+    int y = areas[0].ymin;
+    float *output_elem = output_buf->get_elem(x, y);
+    readSampled(output_elem, x, y, PixelSampler::Nearest);
   }
   else {
     for (const rcti &rect : areas) {
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index c74c17d19d4..ba5e98a9701 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -320,6 +320,16 @@ class NodeOperation {
    */
   unsigned int m_height;
 
+  /**
+   * Operation canvas x coordinate within whole compositing canvas.
+   */
+  int offset_x_;
+
+  /**
+   * Operation canvas y coordinate within whole compositing canvas.
+   */
+  int offset_y_;
+
   /**
    * Flags how to evaluate this operation.
    */
@@ -355,6 +365,9 @@ class NodeOperation {
     return flags;
   }
 
+  rcti get_canvas_area() const;
+  void set_canvas_area(const rcti &rect);
+
   unsigned int getNumberOfInputSockets() const
   {
     return m_inputs.size();
diff --git a/source/blender/compositor/intern/COM_SharedOperationBuffers.cc b/source/blender/compositor/intern/COM_SharedOperationBuffers.cc
index 021e948a727..b2c43147025 100644
--- a/source/blender/compositor/intern/COM_SharedOperationBuffers.cc
+++ b/source/blender/compositor/intern/COM_SharedOperationBuffers.cc
@@ -26,7 +26,7 @@ SharedOperationBuffers::SharedOperationBuffers() : buffers_()
 {
 }
 SharedOperationBuffers::BufferData::BufferData()
-    : buffer(nullptr), render_areas(), registered_reads(0), received_reads(0)
+    : buffer(nullptr), render_areas(), render_bounds({0}), registered_reads(0), received_reads(0)
 {
 }
 
@@ -56,7 +56,9 @@ bool SharedOperationBuffers::is_area_registered(NodeOperation *op, const rcti &a
  */
 void SharedOperationBuffers::register_area(NodeOperation *op, const rcti &area_to_render)
 {
-  get_buffer_data(op).render_areas.append(area_to_render);
+  BufferData &buf_data = get_buffer_data(op);
+  buf_data.render_areas.append(area_to_render);
+  BLI_rcti_union(&buf_data.render_bounds, &area_to_render);
 }
 
 /**
@@ -84,6 +86,14 @@ blender::Span<rcti> SharedOperationBuffers::get_areas_to_render(NodeOperation *o
   return get_buffer_data(op).render_areas.as_span();
 }
 
+/**
+ * Gets the minimum rectangle that includes all rendered areas.
+ */
+const rcti &SharedOperationBuffers::get_render_bounds(NodeOperation *op)
+{
+  return get_buffer_data(op).render_bounds;
+}
+
 /**
  * Whether this operation buffer has already been rendered.
  */
diff --git a/source/blender/compositor/intern/COM_SharedOperationBuffers.h b/source/blender/compositor/intern/COM_SharedOperationBuffers.h
index 9e90a06a0d3..24c80102f9c 100644
--- a/source/blender/compositor/intern/COM_SharedOperationBuffers.h
+++ b/source/blender/compositor/intern/COM_SharedOperationBuffers.h
@@ -40,6 +40,7 @@ class SharedOperationBuffers {
     BufferData();
     std::unique_ptr<MemoryBuffer> buffer;
     blender::Vector<rcti> render_areas;
+    rcti render_bounds;
     int registered_reads;
     int received_reads;
   } BufferData;
@@ -53,6 +54,7 @@ class SharedOperationBuffers {
   bool has_registered_reads(NodeOperation *op);
   void register_read(NodeOperation *read_op);
 
+  const rcti &get_render_bounds(NodeOperation *op);
   blender::Span<rcti> get_areas_to_render(NodeOperation *op);
   bool is_operation_rendered(NodeOperation *op);
   void set_rendered_buffer(NodeOperation *op, std::unique_ptr<MemoryBuffer> buffer);



More information about the Bf-blender-cvs mailing list