[Bf-blender-cvs] [d0d53daeda5] temp-3d-texturing-brush-b: Use compute shader for extraction.

Jeroen Bakker noreply at git.blender.org
Wed Mar 9 17:25:04 CET 2022


Commit: d0d53daeda52480698808547f5abfa5088880309
Author: Jeroen Bakker
Date:   Wed Mar 9 17:24:59 2022 +0100
Branches: temp-3d-texturing-brush-b
https://developer.blender.org/rBd0d53daeda52480698808547f5abfa5088880309

Use compute shader for extraction.

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

M	source/blender/editors/sculpt_paint/CMakeLists.txt
A	source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_c.cc
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/GPU_shader_shared.h
M	source/blender/gpu/intern/gpu_shader_builtin.c
M	source/blender/gpu/intern/gpu_shader_dependency.cc
M	source/blender/gpu/intern/gpu_texture_private.hh
A	source/blender/gpu/shaders/gpu_shader_sculpt_pixel_extraction_comp.glsl
A	source/blender/gpu/shaders/infos/gpu_shader_sculpt_pixel_extraction_info.hh

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

diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 7f044ca405c..3fa8eed7338 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -67,6 +67,7 @@ set(SRC
   sculpt_smooth.c
   sculpt_texture_paint_b.cc
   sculpt_texture_paint_pixel_extraction_b.cc
+  #sculpt_texture_paint_pixel_extraction_c.cc
   sculpt_transform.c
   sculpt_undo.c
   sculpt_uv.c
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_c.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_c.cc
new file mode 100644
index 00000000000..d92bf601ccb
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_c.cc
@@ -0,0 +1,191 @@
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_pbvh.h"
+
+#include "PIL_time_utildefines.h"
+
+#include "BLI_task.h"
+#include "BLI_vector.hh"
+
+#include "IMB_rasterizer.hh"
+
+#include "WM_types.h"
+
+#include "bmesh.h"
+
+#include "ED_uvedit.h"
+
+#include "GPU_compute.h"
+#include "GPU_shader.h"
+#include "GPU_shader_shared.h"
+#include "GPU_texture.h"
+#include "GPU_uniform_buffer.h"
+
+#include "sculpt_intern.h"
+#include "sculpt_texture_paint_intern.hh"
+
+namespace blender::ed::sculpt_paint::texture_paint::barycentric_extraction {
+
+static void init_using_intersection(Object *ob, int totnode, PBVHNode **nodes)
+{
+  Vector<PBVHNode *> nodes_to_initialize;
+  for (int n = 0; n < totnode; n++) {
+    PBVHNode *node = nodes[n];
+    NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+    if (node_data != nullptr) {
+      continue;
+    }
+    node_data = MEM_new<NodeData>(__func__);
+    BKE_pbvh_node_texture_paint_data_set(node, node_data, NodeData::free_func);
+    nodes_to_initialize.append(node);
+  }
+  if (nodes_to_initialize.size() == 0) {
+    return;
+  }
+  printf("%ld nodes to initialize\n", nodes_to_initialize.size());
+
+  Mesh *mesh = static_cast<Mesh *>(ob->data);
+  MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
+  if (ldata_uv == nullptr) {
+    return;
+  }
+
+  SculptSession *ss = ob->sculpt;
+  Vector<TexturePaintPolygon> polygons;
+  for (int n = 0; n < nodes_to_initialize.size(); n++) {
+    PBVHNode *node = nodes[n];
+    PBVHVertexIter vd;
+    BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+      MeshElemMap *vert_map = &ss->pmap[vd.index];
+      for (int j = 0; j < ss->pmap[vd.index].count; j++) {
+        const int poly_index = vert_map->indices[j];
+        const MPoly *p = &ss->mpoly[poly_index];
+        if (p->totloop < 3) {
+          continue;
+        }
+
+        for (int l = 0; l < p->totloop - 2; l++) {
+          const int v1_loop_index = p->loopstart;
+          const int v2_loop_index = p->loopstart + l + 1;
+          const int v3_loop_index = p->loopstart + l + 2;
+          TexturePaintPolygon polygon;
+          polygon.uv[0] = ldata_uv[v1_loop_index].uv;
+          polygon.uv[1] = ldata_uv[v2_loop_index].uv;
+          polygon.uv[2] = ldata_uv[v3_loop_index].uv;
+          polygon.pbvh_node_index = n;
+          polygon.poly_index = poly_index;
+          polygons.append(polygon);
+        }
+      }
+    }
+    BKE_pbvh_vertex_iter_end;
+  }
+  printf("%ld polygons loaded\n", polygons.size());
+
+  GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SCULPT_PIXEL_EXTRACTION);
+  GPU_shader_bind(shader);
+
+  ImBuf *image_buffer = ss->mode.texture_paint.drawing_target;
+  GPU_shader_uniform_1i(shader, "num_polygons", polygons.size());
+
+  const int polygons_loc = GPU_shader_get_ssbo(shader, "polygons");
+  GPUUniformBuf *polygons_buf = GPU_uniformbuf_create_ex(
+      sizeof(TexturePaintPolygon) * polygons.size(), polygons.data(), __func__);
+  BLI_assert(polygons_loc != -1);
+  GPU_uniformbuf_bind(polygons_buf, polygons_loc);
+
+  GPUTexture *pixels_tex = GPU_texture_create_2d(
+      "gpu_shader_compute_2d", image_buffer->x, image_buffer->y, 1, GPU_RGBA32I, nullptr);
+  GPU_texture_image_bind(pixels_tex, GPU_shader_get_texture_binding(shader, "pixels"));
+  int2 calc_size(256, 256);
+  GPU_compute_dispatch(shader, calc_size.x, calc_size.y, 1);
+  // GPU_compute_dispatch(shader, image_buffer->x, image_buffer->y, 1);
+  GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
+  TexturePaintPixel *pixels = static_cast<TexturePaintPixel *>(
+      GPU_texture_read(pixels_tex, GPU_DATA_INT, 0));
+
+#if 1
+  int pixels_added = 0;
+  MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
+  for (int y = 0; y < calc_size.y; y++) {
+    for (int x = 0; x < calc_size.x; x++) {
+      int pixel_offset = y * image_buffer->x + x;
+      float2 uv(float(x) / image_buffer->x, float(y) / image_buffer->y);
+      TexturePaintPixel *pixel = &pixels[pixel_offset];
+      printf("%d %d: %d %d\n", x, y, pixel->poly_index, pixel->pbvh_node_index);
+      if (pixel->poly_index == -1 || pixel->pbvh_node_index == -1) {
+        /* No intersection detected.*/
+        continue;
+      }
+      BLI_assert(pixel->pbvh_node_index < nodes_to_initialize.size());
+      PBVHNode *node = nodes_to_initialize[pixel->pbvh_node_index];
+      NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+      const MPoly *p = &ss->mpoly[pixel->poly_index];
+      const MLoop *loopstart = &ss->mloop[p->loopstart];
+
+      bool intersection_validated = false;
+      for (int l = 0; l < p->totloop - 2; l++) {
+        const int v1_loop_index = p->loopstart;
+        const int v2_loop_index = p->loopstart + l + 1;
+        const int v3_loop_index = p->loopstart + l + 2;
+        const float2 v1_uv = ldata_uv[v1_loop_index].uv;
+        const float2 v2_uv = ldata_uv[v2_loop_index].uv;
+        const float2 v3_uv = ldata_uv[v3_loop_index].uv;
+        float3 weights;
+        barycentric_weights_v2(v1_uv, v2_uv, v3_uv, uv, weights);
+        if (weights[0] < 0.0 || weights[0] > 1.0 || weights[1] < 0.0 || weights[1] > 1.0 ||
+            weights[2] < 0.0 || weights[2] > 1.0) {
+          continue;
+        }
+        const int v1_index = loopstart[0].v;
+        const int v2_index = loopstart[l + 1].v;
+        const int v3_index = loopstart[l + 2].v;
+        const float3 v1_pos = mvert[v1_index].co;
+        const float3 v2_pos = mvert[v2_index].co;
+        const float3 v3_pos = mvert[v3_index].co;
+        float3 local_pos;
+        interp_v3_v3v3v3(local_pos, v1_pos, v2_pos, v3_pos, weights);
+
+        PixelData new_pixel;
+        new_pixel.local_pos = local_pos;
+        new_pixel.pixel_pos = int2(x, y);
+        new_pixel.content = float4(&image_buffer->rect_float[pixel_offset * 4]);
+        new_pixel.flags.dirty = false;
+        node_data->pixels.append(new_pixel);
+        pixels_added += 1;
+
+        intersection_validated = true;
+        break;
+      }
+      BLI_assert(intersection_validated);
+    }
+  }
+  printf("%d pixels added\n", pixels_added);
+#endif
+
+  MEM_freeN(pixels);
+  GPU_shader_unbind();
+  GPU_uniformbuf_free(polygons_buf);
+  GPU_texture_free(pixels_tex);
+}
+}  // 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
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 3ad43ef05af..564a285b277 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -354,6 +354,8 @@ set(GLSL_SRC
   shaders/gpu_shader_gpencil_stroke_frag.glsl
   shaders/gpu_shader_gpencil_stroke_geom.glsl
 
+  shaders/gpu_shader_sculpt_pixel_extraction_comp.glsl
+
   shaders/gpu_shader_cfg_world_clip_lib.glsl
   shaders/gpu_shader_colorspace_lib.glsl
 
@@ -433,6 +435,7 @@ set(SRC_SHADER_CREATE_INFOS
   shaders/infos/gpu_shader_simple_lighting_info.hh
   shaders/infos/gpu_shader_text_info.hh
   shaders/infos/gpu_srgb_to_framebuffer_space_info.hh
+  shaders/infos/gpu_shader_sculpt_pixel_extraction_info.hh
 )
 
 set(SHADER_CREATE_INFOS_CONTENT "")
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index ba4f70f7683..aea9687b126 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -341,6 +341,7 @@ typedef enum eGPUBuiltinShader {
   GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
   /* grease pencil drawing */
   GPU_SHADER_GPENCIL_STROKE,
+  GPU_SHADER_SCULPT_PIXEL_EXTRACTION,
   /* specialized for widget drawing */
   GPU_SHADER_2D_AREA_BORDERS,
   GPU_SHADER_2D_WIDGET_BASE,
diff --git a/source/blender/gpu/GPU_shader_shared.h b/source/blender/gpu/GPU_shader_shared.h
index 2e6f1162cb9..92ffe7af502 100644
--- a/source/blender/gpu/GPU_shader_shared.h
+++ b/source/blender/gpu/GPU_shader_shared.h
@@ -66,3 +66,17 @@ struct MultiRectCallData {
   float4 calls_data[MAX_CALLS * 3];
 };
 BLI_STATIC_ASSERT_ALIGN(struct MultiRectCallData, 16)
+
+struct TexturePaintPolygon {
+  float2 uv[3];
+  int pbvh_node_index;
+  int poly_index;
+};
+BLI_STATIC_ASSERT_ALIGN(struct TexturePaintPolygon, 16)
+
+struct TexturePaintPixel {
+  int pbvh_node_index;
+  int poly_index;
+  int2 _pad;
+};
+BLI_STATIC_ASSERT_ALIGN(struct TexturePaintPixel, 16)
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index dfedb64ce61..bbef84406ef 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -332,6 +332,9 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
 
     [GPU_SHADER_GPENCIL_ST

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list