Share retained stroke preview binding helpers
This commit is contained in:
@@ -18,6 +18,11 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
|
|
||||||
## Recent Reductions
|
## Recent Reductions
|
||||||
|
|
||||||
|
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` live-pass
|
||||||
|
sampler binding, dual/main pass texture binding, checkerboard/background
|
||||||
|
capture wrapping, and final preview copy-back now route through shared local
|
||||||
|
helpers; mixer state execution and per-sample GL ordering remain retained in
|
||||||
|
the preview node.
|
||||||
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` dual-pass and
|
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` dual-pass and
|
||||||
main-pass frame-loop execution plus full-frame copy-back now route through
|
main-pass frame-loop execution plus full-frame copy-back now route through
|
||||||
shared local helpers; checkerboard/background capture ordering, texture-unit
|
shared local helpers; checkerboard/background capture ordering, texture-unit
|
||||||
|
|||||||
@@ -3107,6 +3107,10 @@ Results:
|
|||||||
full-frame copy-back now share one local retained helper surface, while
|
full-frame copy-back now share one local retained helper surface, while
|
||||||
checkerboard/background capture ordering, texture-unit binding, mixer
|
checkerboard/background capture ordering, texture-unit binding, mixer
|
||||||
ownership, and final composite semantics remain in the preview node.
|
ownership, and final composite semantics remain in the preview node.
|
||||||
|
- `NodeStrokePreview` live-pass sampler binding, dual/main pass texture
|
||||||
|
binding, checkerboard/background capture wrapping, and final preview
|
||||||
|
copy-back now share named local helpers, while mixer state execution and
|
||||||
|
per-sample GL ordering remain in the preview node.
|
||||||
- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now
|
- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now
|
||||||
shares the retained stroke execution helper callback surface, while shader
|
shares the retained stroke execution helper callback surface, while shader
|
||||||
setup, pad color selection, framebuffer ownership, and final OpenGL draw
|
setup, pad color selection, framebuffer ownership, and final OpenGL draw
|
||||||
|
|||||||
@@ -509,6 +509,13 @@ Done Checks:
|
|||||||
|
|
||||||
Progress Notes:
|
Progress Notes:
|
||||||
|
|
||||||
|
- 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` live-pass sampler
|
||||||
|
binding, dual/main pass texture binding, checkerboard/background capture
|
||||||
|
wrapping, and final preview copy-back now route through named local helpers;
|
||||||
|
mixer state execution and per-sample GL ordering remain local to the preview
|
||||||
|
node. Next slice should target the remaining mixer-pass state/copy ordering
|
||||||
|
or sample-pass destination callback wrapping without reopening the landed
|
||||||
|
preview live-pass or final-composite helpers.
|
||||||
- 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` dual-pass and
|
- 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` dual-pass and
|
||||||
main-pass frame-loop execution plus full-frame copy-back now route through
|
main-pass frame-loop execution plus full-frame copy-back now route through
|
||||||
shared local helpers; checkerboard/background capture ordering, texture-unit
|
shared local helpers; checkerboard/background capture ordering, texture-unit
|
||||||
|
|||||||
@@ -103,6 +103,14 @@ constexpr std::uint32_t kDual = 3U;
|
|||||||
constexpr std::uint32_t kPattern = 4U;
|
constexpr std::uint32_t kPattern = 4U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace stroke_preview_live_slots {
|
||||||
|
constexpr std::uint32_t kTip = 0U;
|
||||||
|
constexpr std::uint32_t kDestination = 1U;
|
||||||
|
constexpr std::uint32_t kPattern = 2U;
|
||||||
|
constexpr std::uint32_t kMixer = 3U;
|
||||||
|
constexpr std::uint32_t kReservedLinear = 4U;
|
||||||
|
}
|
||||||
|
|
||||||
struct StrokePreviewCompositePassInputs {
|
struct StrokePreviewCompositePassInputs {
|
||||||
glm::vec2 resolution;
|
glm::vec2 resolution;
|
||||||
glm::vec2 pattern_scale;
|
glm::vec2 pattern_scale;
|
||||||
@@ -203,6 +211,110 @@ void copy_stroke_preview_framebuffer_to_texture(
|
|||||||
static_cast<int>(size.y));
|
static_cast<int>(size.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bind_stroke_preview_live_samplers(
|
||||||
|
Sampler& mipmap_sampler,
|
||||||
|
Sampler& linear_sampler,
|
||||||
|
Sampler& repeat_sampler)
|
||||||
|
{
|
||||||
|
mipmap_sampler.bind(stroke_preview_live_slots::kTip);
|
||||||
|
linear_sampler.bind(stroke_preview_live_slots::kDestination);
|
||||||
|
repeat_sampler.bind(stroke_preview_live_slots::kPattern);
|
||||||
|
linear_sampler.bind(stroke_preview_live_slots::kMixer);
|
||||||
|
linear_sampler.bind(stroke_preview_live_slots::kReservedLinear);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_stroke_preview_dual_pass_textures(const Brush& dual_brush)
|
||||||
|
{
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kTip);
|
||||||
|
dual_brush.m_tip_texture ?
|
||||||
|
dual_brush.m_tip_texture->bind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_stroke_preview_main_pass_textures(
|
||||||
|
const Brush& brush,
|
||||||
|
Texture2D& stroke_destination_texture,
|
||||||
|
RTT& mixer_rtt,
|
||||||
|
bool copy_stroke_destination,
|
||||||
|
bool uses_mixer)
|
||||||
|
{
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kTip);
|
||||||
|
brush.m_tip_texture ?
|
||||||
|
brush.m_tip_texture->bind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
|
||||||
|
if (copy_stroke_destination)
|
||||||
|
{
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kDestination);
|
||||||
|
stroke_destination_texture.bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kPattern);
|
||||||
|
brush.m_pattern_texture ?
|
||||||
|
brush.m_pattern_texture->bind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kMixer);
|
||||||
|
uses_mixer ? mixer_rtt.bindTexture() : unbind_texture_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_stroke_preview_background_capture_pass(
|
||||||
|
glm::vec2 size,
|
||||||
|
bool colorize,
|
||||||
|
Texture2D& background_texture,
|
||||||
|
const std::function<void()>& draw_checkerboard)
|
||||||
|
{
|
||||||
|
pp::panopainter::execute_legacy_stroke_preview_background_capture(
|
||||||
|
[&] {
|
||||||
|
const float aspect = size.x / size.y;
|
||||||
|
pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader(
|
||||||
|
pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms {
|
||||||
|
.mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f),
|
||||||
|
.colorize = colorize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
draw_checkerboard();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
background_texture.bind();
|
||||||
|
},
|
||||||
|
[](
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dst_x,
|
||||||
|
int dst_y,
|
||||||
|
int width,
|
||||||
|
int height) {
|
||||||
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyStrokePreviewCopySize {
|
||||||
|
.width = static_cast<int>(size.x),
|
||||||
|
.height = static_cast<int>(size.y),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_stroke_preview_result_to_texture(Texture2D& preview_texture, glm::vec2 size)
|
||||||
|
{
|
||||||
|
pp::panopainter::copy_legacy_stroke_preview_texture(
|
||||||
|
[&] {
|
||||||
|
preview_texture.bind();
|
||||||
|
},
|
||||||
|
[](
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dst_x,
|
||||||
|
int dst_y,
|
||||||
|
int width,
|
||||||
|
int height) {
|
||||||
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyStrokePreviewCopySize {
|
||||||
|
.width = static_cast<int>(size.x),
|
||||||
|
.height = static_cast<int>(size.y),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ClearTarget, typename ComputeFrames, typename BeforeFrame, typename DrawSample>
|
template <typename ClearTarget, typename ComputeFrames, typename BeforeFrame, typename DrawSample>
|
||||||
void execute_stroke_preview_live_pass(
|
void execute_stroke_preview_live_pass(
|
||||||
Texture2D& output_texture,
|
Texture2D& output_texture,
|
||||||
@@ -471,11 +583,10 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
apply_stroke_preview_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
apply_stroke_preview_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
||||||
m_rtt.bindFramebuffer();
|
m_rtt.bindFramebuffer();
|
||||||
m_rtt.clear();
|
m_rtt.clear();
|
||||||
m_sampler_mipmap.bind(0);
|
bind_stroke_preview_live_samplers(
|
||||||
m_sampler_linear.bind(1);
|
m_sampler_mipmap,
|
||||||
m_sampler_linear_repeat.bind(2);
|
m_sampler_linear,
|
||||||
m_sampler_linear.bind(3);
|
m_sampler_linear_repeat);
|
||||||
m_sampler_linear.bind(4);
|
|
||||||
|
|
||||||
const auto& b = m_brush;
|
const auto& b = m_brush;
|
||||||
|
|
||||||
@@ -581,10 +692,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
if (material.dual_pass.enabled)
|
if (material.dual_pass.enabled)
|
||||||
{
|
{
|
||||||
pp::panopainter::setup_legacy_stroke_dual_shader(material.dual_pass.uses_pattern);
|
pp::panopainter::setup_legacy_stroke_dual_shader(material.dual_pass.uses_pattern);
|
||||||
set_active_texture_unit(0U);
|
bind_stroke_preview_dual_pass_textures(*dual_brush);
|
||||||
dual_brush->m_tip_texture ?
|
|
||||||
dual_brush->m_tip_texture->bind() :
|
|
||||||
unbind_texture_2d();
|
|
||||||
execute_stroke_preview_live_pass(
|
execute_stroke_preview_live_pass(
|
||||||
m_tex_dual,
|
m_tex_dual,
|
||||||
size,
|
size,
|
||||||
@@ -605,35 +713,12 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
|
|
||||||
// CHEKCERBOARD
|
// CHEKCERBOARD
|
||||||
|
|
||||||
pp::panopainter::execute_legacy_stroke_preview_background_capture(
|
execute_stroke_preview_background_capture_pass(
|
||||||
[&] {
|
size,
|
||||||
// copy background color to tex2
|
b->m_tip_mix > 0.f || b->m_blend_mode != 0,
|
||||||
const float aspect = size.x / size.y;
|
m_tex_background,
|
||||||
pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader(
|
|
||||||
pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms {
|
|
||||||
.mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f),
|
|
||||||
.colorize = b->m_tip_mix > 0.f || b->m_blend_mode != 0,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&] {
|
[&] {
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
},
|
|
||||||
[&] {
|
|
||||||
//m_rtt.clear({ .3f, .3f, .3f, 1.f });
|
|
||||||
m_tex_background.bind();
|
|
||||||
},
|
|
||||||
[](
|
|
||||||
int src_x,
|
|
||||||
int src_y,
|
|
||||||
int dst_x,
|
|
||||||
int dst_y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
|
||||||
},
|
|
||||||
pp::panopainter::LegacyStrokePreviewCopySize {
|
|
||||||
.width = static_cast<int>(size.x),
|
|
||||||
.height = static_cast<int>(size.y),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// DRAW MAIN BRUSH
|
// DRAW MAIN BRUSH
|
||||||
@@ -645,19 +730,12 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
b->m_tip_wet,
|
b->m_tip_wet,
|
||||||
b->m_tip_noise);
|
b->m_tip_noise);
|
||||||
|
|
||||||
set_active_texture_unit(0U);
|
bind_stroke_preview_main_pass_textures(
|
||||||
b->m_tip_texture->bind();
|
*b,
|
||||||
if (copy_stroke_destination)
|
m_tex,
|
||||||
{
|
m_rtt_mixer,
|
||||||
set_active_texture_unit(1U);
|
copy_stroke_destination,
|
||||||
m_tex.bind(); // tmp swap for blending
|
preview_composite_plan.uses_mixer);
|
||||||
}
|
|
||||||
set_active_texture_unit(2U);
|
|
||||||
b->m_pattern_texture ?
|
|
||||||
b->m_pattern_texture->bind() :
|
|
||||||
unbind_texture_2d();
|
|
||||||
set_active_texture_unit(3U);
|
|
||||||
preview_composite_plan.uses_mixer ? m_rtt_mixer.bindTexture() : unbind_texture_2d();
|
|
||||||
execute_stroke_preview_live_pass(
|
execute_stroke_preview_live_pass(
|
||||||
m_tex,
|
m_tex,
|
||||||
size,
|
size,
|
||||||
@@ -682,7 +760,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
[&](auto& frame, Texture2D& blend_texture, bool copy_destination) {
|
[&](auto& frame, Texture2D& blend_texture, bool copy_destination) {
|
||||||
/*auto rect =*/ stroke_draw_samples(frame.shapes, blend_texture, copy_destination);
|
/*auto rect =*/ stroke_draw_samples(frame.shapes, blend_texture, copy_destination);
|
||||||
});
|
});
|
||||||
set_active_texture_unit(3U);
|
set_active_texture_unit(stroke_preview_live_slots::kMixer);
|
||||||
m_rtt_mixer.unbindTexture();
|
m_rtt_mixer.unbindTexture();
|
||||||
|
|
||||||
// COMPOSITE
|
// COMPOSITE
|
||||||
@@ -704,23 +782,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// copy the result to the actual preview
|
// copy the result to the actual preview
|
||||||
pp::panopainter::copy_legacy_stroke_preview_texture(
|
copy_stroke_preview_result_to_texture(m_tex_preview, size);
|
||||||
[&] {
|
|
||||||
m_tex_preview.bind();
|
|
||||||
},
|
|
||||||
[](
|
|
||||||
int src_x,
|
|
||||||
int src_y,
|
|
||||||
int dst_x,
|
|
||||||
int dst_y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
|
||||||
},
|
|
||||||
pp::panopainter::LegacyStrokePreviewCopySize {
|
|
||||||
.width = static_cast<int>(size.x),
|
|
||||||
.height = static_cast<int>(size.y),
|
|
||||||
});
|
|
||||||
|
|
||||||
m_rtt.unbindFramebuffer();
|
m_rtt.unbindFramebuffer();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user