[Bf-blender-cvs] [795b55b4175] temp-3d-texturing-brush-b: Use struct of structs.

Jeroen Bakker noreply at git.blender.org
Fri Mar 11 11:21:53 CET 2022


Commit: 795b55b41757af2663a74c348bae1db95b07c907
Author: Jeroen Bakker
Date:   Fri Mar 11 11:21:47 2022 +0100
Branches: temp-3d-texturing-brush-b
https://developer.blender.org/rB795b55b41757af2663a74c348bae1db95b07c907

Use struct of structs.

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

M	source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
M	source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
M	source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_b.cc

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

diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
index 7bb27b65803..14d9ab85794 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
@@ -45,6 +45,7 @@ static void do_task_cb_ex(void *__restrict userdata,
   TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
   Object *ob = data->ob;
   SculptSession *ss = ob->sculpt;
+  ImBuf *drawing_target = ss->mode.texture_paint.drawing_target;
   const Brush *brush = data->brush;
   PBVHNode *node = data->nodes[n];
   NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
@@ -60,15 +61,26 @@ static void do_task_cb_ex(void *__restrict userdata,
 
   const float brush_strength = ss->cache->bstrength;
 
-  for (PixelData &pixel : node_data->pixels) {
-    if (!sculpt_brush_test_sq_fn(&test, pixel.local_pos)) {
+  for (int i = 0; i < node_data->pixels.size(); i++) {
+    const float3 &local_pos = node_data->pixels.local_position(i);
+    if (!sculpt_brush_test_sq_fn(&test, local_pos)) {
       continue;
     }
+
+    float4 &color = node_data->pixels.color(i);
+    const int2 &image_coord = node_data->pixels.image_coord(i);
+    /* Although currently the pixel is loaded each time. I expect additional performance
+     * improvement when moving the flushing to higher level on the callstack. */
+    if (!node_data->pixels.is_dirty(i)) {
+      int pixel_index = image_coord.y * drawing_target->x + image_coord.x;
+      copy_v4_v4(color, &drawing_target->rect_float[pixel_index * 4]);
+    }
     const float falloff_strength = BKE_brush_curve_strength(brush, sqrtf(test.dist), test.radius);
-    interp_v3_v3v3(pixel.content, pixel.content, brush_linear, falloff_strength * brush_strength);
-    pixel.content[3] = 1.0f;
-    pixel.flags.dirty = true;
-    BLI_rcti_do_minmax_v(&node_data->dirty_region, pixel.pixel_pos);
+
+    interp_v3_v3v3(color, color, brush_linear, falloff_strength * brush_strength);
+    color[3] = 1.0f;
+    node_data->pixels.mark_dirty(i);
+    BLI_rcti_do_minmax_v(&node_data->dirty_region, image_coord);
     node_data->flags.dirty = true;
   }
 }
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
index 71caf9010ed..ef0fce78b41 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
@@ -1,20 +1,71 @@
 namespace blender::ed::sculpt_paint::texture_paint {
 
 struct PixelData {
-  struct {
-    bool dirty : 1;
-  } flags;
   int2 pixel_pos;
   float3 local_pos;
   float4 content;
 };
 
+struct Pixels {
+  Vector<int2> image_coordinates;
+  Vector<float3> local_positions;
+  Vector<float4> colors;
+  std::vector<bool> dirty;
+
+  uint64_t size() const
+  {
+    return image_coordinates.size();
+  }
+
+  bool is_dirty(uint64_t index) const
+  {
+    return dirty[index];
+  }
+
+  const int2 &image_coord(uint64_t index) const
+  {
+    return image_coordinates[index];
+  }
+  const float3 &local_position(uint64_t index) const
+  {
+    return local_positions[index];
+  }
+
+  const float4 &color(uint64_t index) const
+  {
+    return colors[index];
+  }
+  float4 &color(uint64_t index)
+  {
+    return colors[index];
+  }
+
+  void clear_dirty()
+  {
+    dirty = std::vector<bool>(size(), false);
+  }
+
+  void mark_dirty(uint64_t index)
+  {
+    dirty[index] = true;
+  }
+
+  void append(PixelData &pixel)
+  {
+    image_coordinates.append(pixel.pixel_pos);
+    local_positions.append(pixel.local_pos);
+    colors.append(pixel.content);
+    dirty.push_back(false);
+  }
+};
+
 struct NodeData {
   struct {
     bool dirty : 1;
   } flags;
 
-  Vector<PixelData> pixels;
+  // Vector<PixelData> pixels;
+  Pixels pixels;
   rcti dirty_region;
   rctf uv_region;
 
@@ -29,13 +80,16 @@ struct NodeData {
   void flush(ImBuf &image_buffer)
   {
     flags.dirty = false;
-    for (PixelData &pixel : pixels) {
-      if (pixel.flags.dirty) {
-        const int pixel_offset = (pixel.pixel_pos[1] * image_buffer.x + pixel.pixel_pos[0]);
-        copy_v4_v4(&image_buffer.rect_float[pixel_offset * 4], pixel.content);
-        pixel.flags.dirty = false;
+    for (int i = 0; i < pixels.size(); i++) {
+
+      if (pixels.is_dirty(i)) {
+        const int2 &image_coord = pixels.image_coord(i);
+        const int pixel_offset = (image_coord[1] * image_buffer.x + image_coord[0]);
+        const float4 &color = pixels.color(i);
+        copy_v4_v4(&image_buffer.rect_float[pixel_offset * 4], color);
       }
     }
+    pixels.clear_dirty();
   }
 
   void mark_region(Image &image, ImBuf &image_buffer)
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_b.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_b.cc
index 9680f88d948..09df18270ca 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_b.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_b.cc
@@ -85,7 +85,6 @@ static bool init_using_intersection(SculptSession *ss,
       new_pixel.local_pos = local_pos;
       new_pixel.pixel_pos = xy;
       new_pixel.content = float4(&image_buffer->rect_float[pixel_offset * 4]);
-      new_pixel.flags.dirty = false;
 
       PBVHNode *node = entry.node;
       NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
@@ -114,6 +113,7 @@ static void init_using_intersection(Object *ob, int totnode, PBVHNode **nodes)
     return;
   }
 
+  TIMEIT_START(extract_pixels);
   Mesh *mesh = static_cast<Mesh *>(ob->data);
   MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
   if (ldata_uv == nullptr) {
@@ -188,14 +188,13 @@ static void init_using_intersection(Object *ob, int totnode, PBVHNode **nodes)
       }
     }
   }
+  TIMEIT_END(extract_pixels);
 }
 }  // namespace blender::ed::sculpt_paint::texture_paint::barycentric_extraction
 extern "C" {
 void SCULPT_extract_pixels(Object *ob, PBVHNode **nodes, int totnode)
 {
-  TIMEIT_START(extract_pixels);
   blender::ed::sculpt_paint::texture_paint::barycentric_extraction::init_using_intersection(
       ob, totnode, nodes);
-  TIMEIT_END(extract_pixels);
 }
 }
\ No newline at end of file



More information about the Bf-blender-cvs mailing list