Extract preview main live pass request

This commit is contained in:
2026-06-13 23:50:13 +02:00
parent b9647847f0
commit a2e805f991
4 changed files with 88 additions and 57 deletions

View File

@@ -160,6 +160,11 @@ agent or engineer to remove them without reconstructing context from chat.
through `execute_legacy_node_stroke_preview_main_live_pass(...)`; the through `execute_legacy_node_stroke_preview_main_live_pass(...)`; the
retained path still owns the concrete frame mutation, sample shader setup, retained path still owns the concrete frame mutation, sample shader setup,
and final mixer unbind. and final mixer unbind.
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
now routes the main live-pass request assembly through
`make_stroke_draw_immediate_main_live_pass_request(...)`; the retained path
still owns the concrete frame mutation, sample shader setup, and final mixer
unbind.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` now routes - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` now routes
the remaining per-layer branch orchestration through the remaining per-layer branch orchestration through
`execute_legacy_canvas_draw_merge_layer_composite(...)`; the retained path `execute_legacy_canvas_draw_merge_layer_composite(...)`; the retained path

View File

@@ -1717,7 +1717,7 @@ Completed Task Log:
### STR-036 - Extract Preview Main Live Pass Orchestration ### STR-036 - Extract Preview Main Live Pass Orchestration
Status: Ready Status: Done
Score: no score movement Score: no score movement
Debt: `DEBT-0036` Debt: `DEBT-0036`
Scope: `src/node_stroke_preview.cpp`, `tests/paint_renderer/compositor_tests.cpp` Scope: `src/node_stroke_preview.cpp`, `tests/paint_renderer/compositor_tests.cpp`
@@ -1728,6 +1728,8 @@ Move the remaining `NodeStrokePreview::draw_stroke_immediate()` main live-pass
orchestration into a retained helper so the callsite keeps only branch orchestration into a retained helper so the callsite keeps only branch
selection and direct live-pass dispatch. selection and direct live-pass dispatch.
Closeout: `b9647847`
Done Checks: Done Checks:
- `NodeStrokePreview::draw_stroke_immediate()` no longer owns the main live-pass - `NodeStrokePreview::draw_stroke_immediate()` no longer owns the main live-pass

View File

@@ -790,62 +790,12 @@ void NodeStrokePreview::draw_stroke_immediate()
.execute_main_pass = [&] { .execute_main_pass = [&] {
[[maybe_unused]] const bool main_live_ok = [[maybe_unused]] const bool main_live_ok =
pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass( pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass(
pp::panopainter::LegacyNodeStrokePreviewMainLivePassRequestT<StrokeFrame> { make_stroke_draw_immediate_main_live_pass_request(
.setup_blend_uniforms = [&] { *b,
pp::panopainter::apply_legacy_stroke_blend_uniforms( pass_orchestration,
material.stroke_pass.uses_pattern, copy_stroke_destination,
b->m_tip_mix, zoom,
b->m_tip_wet, size));
b->m_tip_noise);
},
.bind_main_pass_textures = [&] {
bind_stroke_preview_main_pass_textures(
*b,
m_tex,
m_rtt_mixer,
copy_stroke_destination,
material.stroke_pass.uses_mixer);
},
.clear_target = [&] {
m_rtt.clear();
},
.compute_frames = [&] {
return stroke_draw_compute(m_stroke, zoom);
},
.before_frame = [&](auto& frame) {
if (b->m_tip_mix > 0.f)
{
stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect));
}
frame.col = b->m_blend_mode != 0 || b->m_tip_mix > 0.f ?
glm::vec4 { .7, .4, .1, 1 } :
glm::vec4 { 0, 0, 0, 1 };
frame.flow = glm::max(frame.flow, m_min_flow);
},
.setup_sample_shader = [&](auto& frame) {
pp::panopainter::use_legacy_stroke_shader();
pp::panopainter::apply_legacy_stroke_sample_uniforms(
pp::panopainter::LegacyStrokeSampleUniforms {
.color = frame.col,
.alpha = frame.flow,
.opacity = frame.opacity,
});
},
.draw_sample = [&](auto& frame) {
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination);
},
.copy_pass_result = [&] {
copy_stroke_preview_framebuffer_to_texture(
m_tex,
size,
stroke_preview_composite_slots::kStroke);
},
.finish_main_pass = [&] {
set_active_texture_unit(stroke_preview_live_slots::kMixer);
m_rtt_mixer.unbindTexture();
},
});
}, },
.finish_main_pass = [&] {}, .finish_main_pass = [&] {},
.execute_final_composite = [&] { .execute_final_composite = [&] {
@@ -877,6 +827,72 @@ void NodeStrokePreview::draw_stroke_immediate()
apply_stroke_preview_clear_color(cc); apply_stroke_preview_clear_color(cc);
} }
NodeStrokePreview::StrokeMainLivePassRequest
NodeStrokePreview::make_stroke_draw_immediate_main_live_pass_request(
const Brush& brush,
const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration,
bool copy_stroke_destination,
float zoom,
const glm::vec2& size)
{
return StrokeMainLivePassRequest {
.setup_blend_uniforms = [&] {
pp::panopainter::apply_legacy_stroke_blend_uniforms(
pass_orchestration.material.stroke_pass.uses_pattern,
brush.m_tip_mix,
brush.m_tip_wet,
brush.m_tip_noise);
},
.bind_main_pass_textures = [&] {
bind_stroke_preview_main_pass_textures(
brush,
m_tex,
m_rtt_mixer,
copy_stroke_destination,
pass_orchestration.material.stroke_pass.uses_mixer);
},
.clear_target = [&] {
m_rtt.clear();
},
.compute_frames = [&] {
return stroke_draw_compute(m_stroke, zoom);
},
.before_frame = [&](auto& frame) {
if (brush.m_tip_mix > 0.f)
{
stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect));
}
frame.col = brush.m_blend_mode != 0 || brush.m_tip_mix > 0.f ?
glm::vec4 { .7, .4, .1, 1 } :
glm::vec4 { 0, 0, 0, 1 };
frame.flow = glm::max(frame.flow, m_min_flow);
},
.setup_sample_shader = [&](auto& frame) {
pp::panopainter::use_legacy_stroke_shader();
pp::panopainter::apply_legacy_stroke_sample_uniforms(
pp::panopainter::LegacyStrokeSampleUniforms {
.color = frame.col,
.alpha = frame.flow,
.opacity = frame.opacity,
});
},
.draw_sample = [&](auto& frame) {
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination);
},
.copy_pass_result = [&] {
copy_stroke_preview_framebuffer_to_texture(
m_tex,
size,
stroke_preview_composite_slots::kStroke);
},
.finish_main_pass = [&] {
set_active_texture_unit(stroke_preview_live_slots::kMixer);
m_rtt_mixer.unbindTexture();
},
};
}
Image NodeStrokePreview::render_to_image() Image NodeStrokePreview::render_to_image()
{ {
std::lock_guard<std::mutex> _lock(s_render_mutex); std::lock_guard<std::mutex> _lock(s_render_mutex);

View File

@@ -15,6 +15,8 @@ class NodeStrokePreview : public NodeBorder
glm::vec4 m_mixer_rect; glm::vec4 m_mixer_rect;
}; };
using StrokeMainLivePassRequest = pp::panopainter::LegacyNodeStrokePreviewMainLivePassRequestT<StrokeFrame>;
static RTT m_rtt; static RTT m_rtt;
static RTT m_rtt_mixer; static RTT m_rtt_mixer;
static Texture2D m_tex; // blending tmp texture static Texture2D m_tex; // blending tmp texture
@@ -51,6 +53,12 @@ public:
// return rect {origin, size} // return rect {origin, size}
glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex, bool copy_stroke_destination); glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex, bool copy_stroke_destination);
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke, float zoom) const; std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke, float zoom) const;
StrokeMainLivePassRequest make_stroke_draw_immediate_main_live_pass_request(
const Brush& brush,
const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration,
bool copy_stroke_destination,
float zoom,
const glm::vec2& size);
void draw_stroke(); void draw_stroke();
void draw_stroke_immediate(); void draw_stroke_immediate();
Image render_to_image(); Image render_to_image();