Extract preview main pass texture dispatch

This commit is contained in:
2026-06-13 18:34:45 +02:00
parent 547a660412
commit 3a7151ae7f
4 changed files with 121 additions and 18 deletions

View File

@@ -18,6 +18,10 @@ agent or engineer to remove them without reconstructing context from chat.
## Recent Reductions ## Recent Reductions
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
now routes main-pass texture binding through
`bind_legacy_node_stroke_preview_main_pass_textures(...)`; the retained path
still owns the concrete texture objects and mixer binding callbacks.
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()` - 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
no longer duplicates main-pass setup in the outer `prepare_main_pass` block; no longer duplicates main-pass setup in the outer `prepare_main_pass` block;
the retained main-live-pass helper now owns blend-uniform and texture binding the retained main-live-pass helper now owns blend-uniform and texture binding

View File

@@ -234,6 +234,49 @@ struct LegacyNodeStrokePreviewPassOrchestrationPlan {
bool background_colorize = false; bool background_colorize = false;
}; };
struct LegacyNodeStrokePreviewMainPassTextureDispatch {
std::function<void(int)> activate_texture_unit;
std::function<void()> bind_brush_tip;
std::function<void()> bind_stroke_destination;
std::function<void()> bind_pattern;
std::function<void()> bind_mixer;
};
[[nodiscard]] inline LegacyNodeStrokePreviewMainPassTextureDispatch make_legacy_node_stroke_preview_main_pass_texture_dispatch(
std::function<void(int)> activate_texture_unit,
std::function<void()> bind_brush_tip,
std::function<void()> bind_stroke_destination,
std::function<void()> bind_pattern,
std::function<void()> bind_mixer)
{
return LegacyNodeStrokePreviewMainPassTextureDispatch {
.activate_texture_unit = std::move(activate_texture_unit),
.bind_brush_tip = std::move(bind_brush_tip),
.bind_stroke_destination = std::move(bind_stroke_destination),
.bind_pattern = std::move(bind_pattern),
.bind_mixer = std::move(bind_mixer),
};
}
inline void bind_legacy_node_stroke_preview_main_pass_textures(
const LegacyNodeStrokePreviewMainPassTextureDispatch& dispatch,
bool copy_stroke_destination,
bool uses_mixer)
{
dispatch.activate_texture_unit(0);
dispatch.bind_brush_tip();
if (copy_stroke_destination) {
dispatch.activate_texture_unit(1);
dispatch.bind_stroke_destination();
}
dispatch.activate_texture_unit(2);
dispatch.bind_pattern();
dispatch.activate_texture_unit(3);
if (uses_mixer) {
dispatch.bind_mixer();
}
}
template <typename Frame> template <typename Frame>
struct LegacyNodeStrokePreviewMainLivePassRequestT { struct LegacyNodeStrokePreviewMainLivePassRequestT {
std::function<void()> setup_blend_uniforms; std::function<void()> setup_blend_uniforms;

View File

@@ -244,24 +244,29 @@ void bind_stroke_preview_main_pass_textures(
bool copy_stroke_destination, bool copy_stroke_destination,
bool uses_mixer) bool uses_mixer)
{ {
set_active_texture_unit(stroke_preview_live_slots::kTip); pp::panopainter::bind_legacy_node_stroke_preview_main_pass_textures(
brush.m_tip_texture ? pp::panopainter::make_legacy_node_stroke_preview_main_pass_texture_dispatch(
brush.m_tip_texture->bind() : [&](int texture_slot) {
unbind_texture_2d(); set_active_texture_unit(texture_slot);
},
if (copy_stroke_destination) [&] {
{ brush.m_tip_texture ?
set_active_texture_unit(stroke_preview_live_slots::kDestination); brush.m_tip_texture->bind() :
stroke_destination_texture.bind(); unbind_texture_2d();
} },
[&] {
set_active_texture_unit(stroke_preview_live_slots::kPattern); stroke_destination_texture.bind();
brush.m_pattern_texture ? },
brush.m_pattern_texture->bind() : [&] {
unbind_texture_2d(); brush.m_pattern_texture ?
brush.m_pattern_texture->bind() :
set_active_texture_unit(stroke_preview_live_slots::kMixer); unbind_texture_2d();
uses_mixer ? mixer_rtt.bindTexture() : unbind_texture_2d(); },
[&] {
mixer_rtt.bindTexture();
}),
copy_stroke_destination,
uses_mixer);
} }
void bind_stroke_preview_destination_texture(Texture2D& texture) void bind_stroke_preview_destination_texture(Texture2D& texture)

View File

@@ -2611,6 +2611,54 @@ void legacy_node_stroke_preview_main_live_pass_preserves_order(pp::tests::Harnes
PP_EXPECT(h, !invalid); PP_EXPECT(h, !invalid);
} }
void legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order(pp::tests::Harness& h)
{
std::vector<std::string> steps;
const auto run = [&](bool copy_stroke_destination, bool uses_mixer) {
steps.clear();
pp::panopainter::bind_legacy_node_stroke_preview_main_pass_textures(
pp::panopainter::make_legacy_node_stroke_preview_main_pass_texture_dispatch(
[&](int texture_slot) {
steps.emplace_back("unit:" + std::to_string(texture_slot));
},
[&] {
steps.emplace_back("bind_tip");
},
[&] {
steps.emplace_back("bind_destination");
},
[&] {
steps.emplace_back("bind_pattern");
},
[&] {
steps.emplace_back("bind_mixer");
}),
copy_stroke_destination,
uses_mixer);
};
run(false, false);
PP_EXPECT(h, steps == std::vector<std::string> {
"unit:0",
"bind_tip",
"unit:2",
"bind_pattern",
"unit:3",
});
run(true, true);
PP_EXPECT(h, steps == std::vector<std::string> {
"unit:0",
"bind_tip",
"unit:1",
"bind_destination",
"unit:2",
"bind_pattern",
"unit:3",
"bind_mixer",
});
}
void legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs(pp::tests::Harness& h) void legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs(pp::tests::Harness& h)
{ {
const auto plan = pp::panopainter::plan_legacy_node_stroke_preview_stroke_setup( const auto plan = pp::panopainter::plan_legacy_node_stroke_preview_stroke_setup(
@@ -3204,6 +3252,9 @@ int main()
harness.run( harness.run(
"legacy_node_stroke_preview_main_live_pass_preserves_order", "legacy_node_stroke_preview_main_live_pass_preserves_order",
legacy_node_stroke_preview_main_live_pass_preserves_order); legacy_node_stroke_preview_main_live_pass_preserves_order);
harness.run(
"legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order",
legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order);
harness.run( harness.run(
"legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs", "legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs",
legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs); legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs);