diff options
author | Jeroen Bakker <jeroen@blender.org> | 2022-10-03 15:59:12 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2022-10-03 15:59:18 +0300 |
commit | 78f46baa475ae817d6f87d95afab0803d160190b (patch) | |
tree | beee9e18d0e89ea69d2dc1b29a75833474fba620 /source/blender/editors | |
parent | b0d6318436236063a3a156d8d19720513878fc1b (diff) |
Only draw nodes that are used during in current paint frame.
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 10 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_paint_image.cc | 57 |
2 files changed, 46 insertions, 21 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 3725e264236..752a59a968b 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5525,18 +5525,16 @@ static void sculpt_stroke_redraw(const bContext *C, struct PaintStroke *UNUSED(stroke), bool is_final) { - /* TODO(jbakker): this function should not be called redraw as it doesn't do redrawing, but - * triggers batched step drawing and downloading of results and update undo steps for the paint - * brush with a canvas target.*/ - printf("%s %d\n", __func__, is_final); + /* TODO(jbakker): this callback should not be named redraw as in this case it doesn't do + * redrawing, but triggers batched step drawing and downloading of results and update undo steps + * for the paint brush with a canvas target.*/ Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); ToolSettings *tool_settings = CTX_data_tool_settings(C); - sculpt_flush_batches( - sd, ob, brush, &tool_settings->paint_mode); + sculpt_flush_batches(sd, ob, brush, &tool_settings->paint_mode); if (!ss->cache) { return; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc index f3cf982c667..46741982354 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc +++ b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc @@ -499,6 +499,8 @@ static void ensure_gpu_buffers(TexturePaintingUserData &data) SculptSession &ss = *data.ob->sculpt; if (!ss.mode.texture_paint.gpu_data) { ss.mode.texture_paint.gpu_data = MEM_new<GPUSculptPaintData>(__func__); + PBVH *pbvh = ss.pbvh; + BKE_pbvh_frame_selection_clear(pbvh); } for (PBVHNode *node : MutableSpan<PBVHNode *>(data.nodes, data.nodes_len)) { @@ -508,7 +510,7 @@ static void ensure_gpu_buffers(TexturePaintingUserData &data) } static void gpu_painting_paint_step(TexturePaintingUserData &data, - ImageTileWrapper &image_tile, + TileNumber tile_number, ImBuf *image_buffer, GPUTexture **tex_ptr, GPUUniformBuf *paint_brush_buf, @@ -543,7 +545,7 @@ static void gpu_painting_paint_step(TexturePaintingUserData &data, } for (UDIMTilePixels &tile_pixels : node_data.tiles) { - if (tile_pixels.tile_number != image_tile.get_tile_number()) { + if (tile_pixels.tile_number != tile_number) { continue; } @@ -558,7 +560,8 @@ static void gpu_painting_paint_step(TexturePaintingUserData &data, GPU_texture_image_bind(tex, GPU_shader_get_texture_binding(shader, "out_img")); GPU_storagebuf_bind(paint_step_buf, GPU_shader_get_ssbo(shader, "paint_step_buf")); GPU_shader_uniform_2iv(shader, "paint_step_range", paint_step_range); - GPU_uniformbuf_bind(paint_brush_buf, GPU_shader_get_uniform_block(shader, "ren")); + GPU_uniformbuf_bind(paint_brush_buf, + GPU_shader_get_uniform_block(shader, "paint_brush_buf")); GPU_storagebuf_bind(vert_coord_buf, GPU_shader_get_ssbo(shader, "vert_coord_buf")); GPU_storagebuf_bind(node_data.triangles.gpu_buffer, GPU_shader_get_ssbo(shader, "paint_input")); @@ -654,6 +657,29 @@ static void dispatch_gpu_painting(TexturePaintingUserData &data) batches.steps.append(paint_step); } +static void update_frame_selection(TexturePaintingUserData &data) +{ + for (PBVHNode *node : MutableSpan<PBVHNode *>(data.nodes, data.nodes_len)) { + BKE_pbvh_node_frame_selection_mark(node); + } +} + +using TileNumbers = Vector<TileNumber, 8>; + +/* Collect all tile numbers that the node selection is using. This will reduce the read misses + * when handling multiple Tiles. Most likely only a small amount of tiles are actually used. */ +static TileNumbers collect_active_tile_numbers(const TexturePaintingUserData &data) +{ + Vector<TileNumber, 8> result; + for (PBVHNode *node : Span<PBVHNode *>(data.nodes, data.nodes_len)) { + NodeData &node_data = BKE_pbvh_pixels_node_data_get(*node); + for (const UDIMTilePixels &tile : node_data.tiles) { + result.append_non_duplicates(tile.tile_number); + } + } + return result; +} + static void dispatch_gpu_batches(TexturePaintingUserData &data) { SculptSession &ss = *data.ob->sculpt; @@ -674,21 +700,23 @@ static void dispatch_gpu_batches(TexturePaintingUserData &data) GPUUniformBuf *paint_brush_buf = GPU_uniformbuf_create_ex( sizeof(PaintBrushData), &paint_brush, "PaintBrushData"); - GPUTexture *tex; + GPUTexture *tex = nullptr; Image &image = *data.image_data.image; ImageUser local_image_user = *data.image_data.image_user; - LISTBASE_FOREACH (ImageTile *, tile, &image.tiles) { - ImageTileWrapper image_tile(tile); - local_image_user.tile = image_tile.get_tile_number(); + TileNumbers tile_numbers = collect_active_tile_numbers(data); + for (TileNumber tile_number : tile_numbers) { + + local_image_user.tile = tile_number; ImBuf *image_buffer = BKE_image_acquire_ibuf(&image, &local_image_user, nullptr); if (image_buffer == nullptr) { continue; } + GPU_debug_group_begin("Paint tile"); gpu_painting_paint_step(data, - image_tile, + tile_number, image_buffer, &tex, paint_brush_buf, @@ -696,6 +724,7 @@ static void dispatch_gpu_batches(TexturePaintingUserData &data) paint_step_range, vert_coord_buf); gpu_painting_image_merge(data, *data.image_data.image, local_image_user, *image_buffer, tex); + GPU_debug_group_end(); BKE_image_release_ibuf(data.image_data.image, image_buffer, nullptr); } @@ -776,13 +805,8 @@ void SCULPT_do_paint_brush_image( if (SCULPT_use_image_paint_compute()) { ensure_gpu_buffers(data); - // update GPU buffers when they don't exist. - // update Image when it doesn't exist. - // go over given nodes and dispatch those nodes. + update_frame_selection(data); dispatch_gpu_painting(data); - // Copy result to the image gpu buffer - // Copy back should happen at the end of the stroke, but for testing we could do it here and - // move it. } else { TaskParallelSettings settings; @@ -808,7 +832,10 @@ void SCULPT_paint_image_batches_flush(PaintModeSettings *paint_mode_settings, TexturePaintingUserData data = {nullptr}; data.ob = ob; data.brush = brush; - BKE_pbvh_search_gather(ob->sculpt->pbvh, nullptr, nullptr, &data.nodes, &data.nodes_len); + BKE_pbvh_search_gather_frame_selected(ob->sculpt->pbvh, &data.nodes, &data.nodes_len); + if (data.nodes_len == 0) { + return; + } if (ImageData::init_active_image(ob, &data.image_data, paint_mode_settings)) { GPU_debug_group_begin("SCULPT_paint_brush"); |