Share retained stroke sampler dispatch helpers

This commit is contained in:
2026-06-13 10:36:52 +02:00
parent 24c0452229
commit 0a5e7302bc
5 changed files with 309 additions and 69 deletions

View File

@@ -634,12 +634,6 @@ void Canvas::stroke_draw()
apply_canvas_viewport(0, 0, m_width, m_height);
m_sampler_brush.bind(0);
m_sampler_nearest.bind(1);
m_sampler_stencil.bind(2);
m_sampler.bind(3);
//m_sampler_linear.bind(5);
glm::vec2 patt_scale = glm::vec2(brush->m_pattern_scale);
if (brush->m_pattern_flipx) patt_scale.x *= -1.f;
if (brush->m_pattern_flipy) patt_scale.y *= -1.f;
@@ -687,6 +681,24 @@ void Canvas::stroke_draw()
.slot = 3,
},
};
constexpr std::array live_pass_sampler_bindings {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
.slot = 0,
},
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination,
.slot = 1,
},
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::pattern,
.slot = 2,
},
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer,
.slot = 3,
},
};
constexpr std::array main_pass_texture_unbindings {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer,
@@ -697,26 +709,60 @@ void Canvas::stroke_draw()
.slot = 0,
},
};
const pp::panopainter::LegacyCanvasStrokeSamplerDispatch live_pass_sampler_dispatch {
.bind_brush_tip_sampler = [&](int slot) {
m_sampler_brush.bind(slot);
},
.unbind_brush_tip_sampler = [&] {
m_sampler_brush.unbind();
},
.bind_stroke_destination_sampler = [&](int slot) {
m_sampler_nearest.bind(slot);
},
.unbind_stroke_destination_sampler = [&] {
m_sampler_nearest.unbind();
},
.bind_pattern_sampler = [&](int slot) {
m_sampler_stencil.bind(slot);
},
.unbind_pattern_sampler = [&] {
m_sampler_stencil.unbind();
},
.bind_mixer_sampler = [&](int slot) {
m_sampler.bind(slot);
},
.unbind_mixer_sampler = [&] {
m_sampler.unbind();
},
};
const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch main_pass_texture_dispatch {
.activate_texture_unit = [&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
.bind_brush_tip = [&] {
brush->m_tip_texture->bind();
},
.unbind_brush_tip = [&] {
brush->m_tip_texture->unbind();
},
.bind_pattern = [&] {
brush->m_pattern_texture ?
brush->m_pattern_texture->bind() :
unbind_texture_2d();
},
.bind_mixer = [&] {
m_mixer.bindTexture();
},
.unbind_mixer = [&] {
m_mixer.unbindTexture();
},
};
pp::panopainter::bind_legacy_canvas_stroke_sampler_inputs(
live_pass_sampler_bindings,
live_pass_sampler_dispatch);
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
main_pass_texture_bindings,
[&](auto input, int texture_slot) {
set_active_texture_unit(texture_slot);
switch (input) {
case pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip:
brush->m_tip_texture->bind();
break;
case pp::panopainter::LegacyCanvasStrokeTextureInput::pattern:
brush->m_pattern_texture ?
brush->m_pattern_texture->bind() :
unbind_texture_2d();
break;
case pp::panopainter::LegacyCanvasStrokeTextureInput::mixer:
m_mixer.bindTexture();
break;
case pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination:
break;
}
});
main_pass_texture_dispatch);
auto frames = stroke_draw_compute(*m_current_stroke);
@@ -755,20 +801,7 @@ void Canvas::stroke_draw()
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
main_pass_texture_unbindings,
[&](auto input, int texture_slot) {
set_active_texture_unit(texture_slot);
switch (input) {
case pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip:
brush->m_tip_texture->unbind();
break;
case pp::panopainter::LegacyCanvasStrokeTextureInput::mixer:
m_mixer.unbindTexture();
break;
case pp::panopainter::LegacyCanvasStrokeTextureInput::pattern:
case pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination:
break;
}
});
main_pass_texture_dispatch);
// pad stroke
// In order to mitigate color bleeding at the edge of shapes in transparent layers
@@ -808,12 +841,13 @@ void Canvas::stroke_draw()
.bind_destination_texture = [&](int face_index) {
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
pad_destination_texture_binding,
[&](auto input, int texture_slot) {
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination) {
return;
}
set_active_texture_unit(texture_slot);
m_tex[face_index].bind();
pp::panopainter::LegacyCanvasStrokeTextureInputDispatch {
.activate_texture_unit = [&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
.bind_stroke_destination = [&] {
m_tex[face_index].bind();
},
});
},
.copy_framebuffer_to_destination_texture =
@@ -829,12 +863,13 @@ void Canvas::stroke_draw()
.unbind_destination_texture = [&](int face_index) {
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
pad_destination_texture_binding,
[&](auto input, int texture_slot) {
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination) {
return;
}
set_active_texture_unit(texture_slot);
m_tex[face_index].unbind();
pp::panopainter::LegacyCanvasStrokeTextureInputDispatch {
.activate_texture_unit = [&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
.unbind_stroke_destination = [&] {
m_tex[face_index].unbind();
},
});
},
.draw_pad = [&] {
@@ -860,14 +895,20 @@ void Canvas::stroke_draw()
};
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
dual_pass_texture_bindings,
[&](auto input, int texture_slot) {
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip) {
return;
}
set_active_texture_unit(texture_slot);
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->bind() :
unbind_texture_2d();
pp::panopainter::LegacyCanvasStrokeTextureInputDispatch {
.activate_texture_unit = [&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
.bind_brush_tip = [&] {
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->bind() :
unbind_texture_2d();
},
.unbind_brush_tip = [&] {
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->unbind() :
unbind_texture_2d();
},
});
auto frames_dual = stroke_draw_compute(*m_dual_stroke);
const std::array<bool, 6> include_dual_dirty =
@@ -895,20 +936,21 @@ void Canvas::stroke_draw()
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
dual_pass_texture_bindings,
[&](auto input, int texture_slot) {
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip) {
return;
}
set_active_texture_unit(texture_slot);
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->unbind() :
unbind_texture_2d();
pp::panopainter::LegacyCanvasStrokeTextureInputDispatch {
.activate_texture_unit = [&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
.unbind_brush_tip = [&] {
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->unbind() :
unbind_texture_2d();
},
});
}
m_sampler_brush.unbind();
m_sampler_nearest.unbind();
m_sampler_stencil.unbind();
pp::panopainter::unbind_legacy_canvas_stroke_sampler_inputs(
live_pass_sampler_bindings,
live_pass_sampler_dispatch);
apply_canvas_viewport(vp.x, vp.y, vp.width, vp.height);
apply_canvas_clear_color(cc);

View File

@@ -49,6 +49,29 @@ struct LegacyCanvasStrokeTextureBinding {
int slot = 0;
};
struct LegacyCanvasStrokeTextureInputDispatch {
std::function<void(int)> activate_texture_unit;
std::function<void()> bind_brush_tip;
std::function<void()> unbind_brush_tip;
std::function<void()> bind_stroke_destination;
std::function<void()> unbind_stroke_destination;
std::function<void()> bind_pattern;
std::function<void()> unbind_pattern;
std::function<void()> bind_mixer;
std::function<void()> unbind_mixer;
};
struct LegacyCanvasStrokeSamplerDispatch {
std::function<void(int)> bind_brush_tip_sampler;
std::function<void()> unbind_brush_tip_sampler;
std::function<void(int)> bind_stroke_destination_sampler;
std::function<void()> unbind_stroke_destination_sampler;
std::function<void(int)> bind_pattern_sampler;
std::function<void()> unbind_pattern_sampler;
std::function<void(int)> bind_mixer_sampler;
std::function<void()> unbind_mixer_sampler;
};
struct LegacyCanvasStrokeFaceDirtyRequest {
pp::renderer::Extent2D extent {};
glm::vec4 previous_accumulated_dirty_box {};
@@ -232,6 +255,165 @@ inline void unbind_legacy_canvas_stroke_texture_inputs(
}
}
inline void bind_legacy_canvas_stroke_texture_input(
LegacyCanvasStrokeTextureInput input,
const LegacyCanvasStrokeTextureInputDispatch& dispatch)
{
switch (input) {
case LegacyCanvasStrokeTextureInput::brush_tip:
if (dispatch.bind_brush_tip) {
dispatch.bind_brush_tip();
}
break;
case LegacyCanvasStrokeTextureInput::stroke_destination:
if (dispatch.bind_stroke_destination) {
dispatch.bind_stroke_destination();
}
break;
case LegacyCanvasStrokeTextureInput::pattern:
if (dispatch.bind_pattern) {
dispatch.bind_pattern();
}
break;
case LegacyCanvasStrokeTextureInput::mixer:
if (dispatch.bind_mixer) {
dispatch.bind_mixer();
}
break;
}
}
inline void unbind_legacy_canvas_stroke_texture_input(
LegacyCanvasStrokeTextureInput input,
const LegacyCanvasStrokeTextureInputDispatch& dispatch)
{
switch (input) {
case LegacyCanvasStrokeTextureInput::brush_tip:
if (dispatch.unbind_brush_tip) {
dispatch.unbind_brush_tip();
}
break;
case LegacyCanvasStrokeTextureInput::stroke_destination:
if (dispatch.unbind_stroke_destination) {
dispatch.unbind_stroke_destination();
}
break;
case LegacyCanvasStrokeTextureInput::pattern:
if (dispatch.unbind_pattern) {
dispatch.unbind_pattern();
}
break;
case LegacyCanvasStrokeTextureInput::mixer:
if (dispatch.unbind_mixer) {
dispatch.unbind_mixer();
}
break;
}
}
inline void bind_legacy_canvas_stroke_sampler_input(
LegacyCanvasStrokeTextureInput input,
int slot,
const LegacyCanvasStrokeSamplerDispatch& dispatch)
{
switch (input) {
case LegacyCanvasStrokeTextureInput::brush_tip:
if (dispatch.bind_brush_tip_sampler) {
dispatch.bind_brush_tip_sampler(slot);
}
break;
case LegacyCanvasStrokeTextureInput::stroke_destination:
if (dispatch.bind_stroke_destination_sampler) {
dispatch.bind_stroke_destination_sampler(slot);
}
break;
case LegacyCanvasStrokeTextureInput::pattern:
if (dispatch.bind_pattern_sampler) {
dispatch.bind_pattern_sampler(slot);
}
break;
case LegacyCanvasStrokeTextureInput::mixer:
if (dispatch.bind_mixer_sampler) {
dispatch.bind_mixer_sampler(slot);
}
break;
}
}
inline void unbind_legacy_canvas_stroke_sampler_input(
LegacyCanvasStrokeTextureInput input,
const LegacyCanvasStrokeSamplerDispatch& dispatch)
{
switch (input) {
case LegacyCanvasStrokeTextureInput::brush_tip:
if (dispatch.unbind_brush_tip_sampler) {
dispatch.unbind_brush_tip_sampler();
}
break;
case LegacyCanvasStrokeTextureInput::stroke_destination:
if (dispatch.unbind_stroke_destination_sampler) {
dispatch.unbind_stroke_destination_sampler();
}
break;
case LegacyCanvasStrokeTextureInput::pattern:
if (dispatch.unbind_pattern_sampler) {
dispatch.unbind_pattern_sampler();
}
break;
case LegacyCanvasStrokeTextureInput::mixer:
if (dispatch.unbind_mixer_sampler) {
dispatch.unbind_mixer_sampler();
}
break;
}
}
template <std::size_t BindingCount>
inline void bind_legacy_canvas_stroke_texture_inputs(
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
const LegacyCanvasStrokeTextureInputDispatch& dispatch)
{
for (const auto& binding : bindings) {
if (dispatch.activate_texture_unit) {
dispatch.activate_texture_unit(binding.slot);
}
bind_legacy_canvas_stroke_texture_input(binding.input, dispatch);
}
}
template <std::size_t BindingCount>
inline void unbind_legacy_canvas_stroke_texture_inputs(
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
const LegacyCanvasStrokeTextureInputDispatch& dispatch)
{
for (const auto& binding : bindings) {
if (dispatch.activate_texture_unit) {
dispatch.activate_texture_unit(binding.slot);
}
unbind_legacy_canvas_stroke_texture_input(binding.input, dispatch);
}
}
template <std::size_t BindingCount>
inline void bind_legacy_canvas_stroke_sampler_inputs(
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
const LegacyCanvasStrokeSamplerDispatch& dispatch)
{
for (const auto& binding : bindings) {
bind_legacy_canvas_stroke_sampler_input(binding.input, binding.slot, dispatch);
}
}
template <std::size_t BindingCount>
inline void unbind_legacy_canvas_stroke_sampler_inputs(
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
const LegacyCanvasStrokeSamplerDispatch& dispatch)
{
for (const auto& binding : bindings) {
unbind_legacy_canvas_stroke_sampler_input(binding.input, dispatch);
}
}
template <typename Frames, typename BeginFrame, typename BeginFace, typename ExecuteSample, typename FinishFace>
std::size_t execute_legacy_canvas_stroke_frame_samples(
Frames&& frames,