Extract retained stroke preview pass orchestration plan

This commit is contained in:
2026-06-13 11:43:31 +02:00
parent 67c594129d
commit cf92181ae4
9 changed files with 306 additions and 129 deletions

View File

@@ -1,7 +1,6 @@
#pragma once
#include "shader.h"
#include "util.h"
#include <functional>

View File

@@ -3,6 +3,7 @@
#include "../libs/glm/glm/glm.hpp"
#include "../libs/glm/glm/ext/matrix_clip_space.hpp"
#include "legacy_canvas_stroke_shader_services.h"
#include "legacy_canvas_stroke_services.h"
#include "paint_renderer/compositor.h"
@@ -224,6 +225,98 @@ struct LegacyNodeStrokePreviewPassSequenceRequest {
return true;
}
struct LegacyNodeStrokePreviewPassOrchestrationPlan {
pp::paint_renderer::CanvasStrokeFeedbackPlan feedback {};
pp::paint_renderer::CanvasStrokeMaterialPlan material {};
pp::paint_renderer::StrokePreviewCompositePlan composite {};
LegacyStrokeShaderSetupUniforms stroke_shader {};
bool copy_stroke_destination = false;
bool background_colorize = false;
};
struct LegacyNodeStrokePreviewPassOrchestrationRequest {
pp::renderer::RenderDeviceFeatures features {};
glm::vec2 preview_size {};
float pattern_scale = 0.0f;
bool pattern_flipx = false;
bool pattern_flipy = false;
bool pattern_invert = false;
float pattern_brightness = 0.0f;
float pattern_contrast = 0.0f;
float pattern_depth = 0.0f;
bool pattern_rand_offset = false;
bool pattern_enabled = false;
bool pattern_eachsample = false;
float tip_mix = 0.0f;
float tip_wet = 0.0f;
float tip_noise = 0.0f;
bool dual_enabled = false;
int dual_blend_mode = 0;
float dual_opacity = 0.0f;
int pattern_blend_mode = 0;
int blend_mode = 0;
glm::mat4 mvp { 1.0f };
};
[[nodiscard]] inline LegacyNodeStrokePreviewPassOrchestrationPlan
plan_legacy_node_stroke_preview_pass_orchestration(
const LegacyNodeStrokePreviewPassOrchestrationRequest& request) noexcept
{
LegacyNodeStrokePreviewPassOrchestrationPlan plan;
plan.feedback = plan_legacy_node_stroke_preview_feedback(
request.features,
static_cast<int>(request.preview_size.x),
static_cast<int>(request.preview_size.y));
plan.copy_stroke_destination = !plan.feedback.reads_destination_color;
plan.material = plan_legacy_canvas_stroke_material(
pp::paint_renderer::CanvasStrokeMaterialRequest {
.destination_feedback_needed = plan.copy_stroke_destination,
.pattern_enabled = request.pattern_enabled,
.pattern_eachsample = request.pattern_eachsample,
.wet_blend = request.tip_wet > 0.0f,
.mix_blend = request.tip_mix > 0.0f,
.noise_enabled = request.tip_noise > 0.0f,
.dual_brush_enabled = request.dual_enabled,
.dual_blend_mode = request.dual_blend_mode,
.pattern_blend_mode = request.pattern_blend_mode,
.dual_alpha = request.dual_opacity,
});
plan.composite = plan_legacy_node_stroke_preview_composite(
request.tip_mix > 0.0f,
plan.material.composite_pass.use_dual,
plan.material.composite_pass.use_pattern);
glm::vec2 preview_pattern_scale(request.pattern_scale);
if (request.pattern_flipx) {
preview_pattern_scale.x *= -1.0f;
}
if (request.pattern_flipy) {
preview_pattern_scale.y *= -1.0f;
}
plan.stroke_shader = LegacyStrokeShaderSetupUniforms {
.resolution = request.preview_size,
.pattern = {
.scale = preview_pattern_scale,
.invert = static_cast<float>(request.pattern_invert),
.brightness = request.pattern_brightness,
.contrast = request.pattern_contrast,
.depth = request.pattern_depth,
.blend_mode = request.pattern_blend_mode,
.offset = glm::vec2(request.pattern_rand_offset ? 0.5f : 0.0f),
},
.mvp = request.mvp,
.uses_destination_feedback = plan.copy_stroke_destination,
.uses_pattern = false,
.mix_alpha = 0.0f,
.wet = 0.0f,
.noise = 0.0f,
.set_opacity = false,
};
plan.background_colorize = request.tip_mix > 0.0f || request.blend_mode != 0;
return plan;
}
struct LegacyNodeStrokePreviewStrokePoint {
glm::vec3 position {};
float pressure = 0.0f;

View File

@@ -27,35 +27,6 @@ pp::renderer::RenderDeviceFeatures stroke_preview_render_device_features() noexc
return ShaderManager::render_device_features();
}
pp::paint_renderer::CanvasStrokeFeedbackPlan stroke_preview_destination_feedback_plan(
int width,
int height) noexcept
{
return pp::panopainter::plan_legacy_node_stroke_preview_feedback(
stroke_preview_render_device_features(),
width,
height);
}
pp::paint_renderer::CanvasStrokeMaterialPlan stroke_preview_material_plan(
const Brush& brush,
bool destination_feedback_needed) noexcept
{
return pp::panopainter::plan_legacy_canvas_stroke_material(
pp::paint_renderer::CanvasStrokeMaterialRequest {
.destination_feedback_needed = destination_feedback_needed,
.pattern_enabled = brush.m_pattern_enabled,
.pattern_eachsample = brush.m_pattern_eachsample,
.wet_blend = brush.m_tip_wet > 0.F,
.mix_blend = brush.m_tip_mix > 0.F,
.noise_enabled = brush.m_tip_noise > 0.F,
.dual_brush_enabled = brush.m_dual_enabled,
.dual_blend_mode = brush.m_dual_blend_mode,
.pattern_blend_mode = brush.m_pattern_blend_mode,
.dual_alpha = brush.m_dual_opacity,
});
}
void set_active_texture_unit(std::uint32_t unit_index)
{
pp::legacy::ui_gl::activate_texture_unit(unit_index, "NodeStrokePreview");
@@ -761,33 +732,33 @@ void NodeStrokePreview::draw_stroke_immediate()
const glm::vec2 patt_scale = stroke_setup.pattern_scale;
apply_stroke_preview_capability(pp::renderer::gl::blend_state(), false);
const auto stroke_feedback = stroke_preview_destination_feedback_plan(m_rtt.getWidth(), m_rtt.getHeight());
const bool copy_stroke_destination = !stroke_feedback.reads_destination_color;
const auto material = stroke_preview_material_plan(*b, copy_stroke_destination);
const auto preview_composite_plan = pp::panopainter::plan_legacy_node_stroke_preview_composite(
b->m_tip_mix > 0.0f,
material.composite_pass.use_dual,
material.composite_pass.use_pattern);
pp::panopainter::setup_legacy_stroke_shader(
pp::panopainter::LegacyStrokeShaderSetupUniforms {
.resolution = size,
.pattern = {
.scale = patt_scale,
.invert = static_cast<float>(b->m_pattern_invert),
.brightness = b->m_pattern_brightness,
.contrast = b->m_pattern_contrast,
.depth = b->m_pattern_depth,
.blend_mode = b->m_pattern_blend_mode,
.offset = glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f),
},
const auto pass_orchestration = pp::panopainter::plan_legacy_node_stroke_preview_pass_orchestration(
pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationRequest {
.features = stroke_preview_render_device_features(),
.preview_size = size,
.pattern_scale = b->m_pattern_scale,
.pattern_flipx = b->m_pattern_flipx,
.pattern_flipy = b->m_pattern_flipy,
.pattern_invert = b->m_pattern_invert,
.pattern_brightness = b->m_pattern_brightness,
.pattern_contrast = b->m_pattern_contrast,
.pattern_depth = b->m_pattern_depth,
.pattern_rand_offset = b->m_pattern_rand_offset,
.pattern_enabled = b->m_pattern_enabled,
.pattern_eachsample = b->m_pattern_eachsample,
.tip_mix = b->m_tip_mix,
.tip_wet = b->m_tip_wet,
.tip_noise = b->m_tip_noise,
.dual_enabled = b->m_dual_enabled,
.dual_blend_mode = b->m_dual_blend_mode,
.dual_opacity = b->m_dual_opacity,
.pattern_blend_mode = b->m_pattern_blend_mode,
.blend_mode = b->m_blend_mode,
.mvp = ortho_proj,
.uses_destination_feedback = copy_stroke_destination,
.uses_pattern = false,
.mix_alpha = 0.0f,
.wet = 0.0f,
.noise = 0.0f,
.set_opacity = false,
});
const bool copy_stroke_destination = pass_orchestration.copy_stroke_destination;
const auto& material = pass_orchestration.material;
pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader);
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_pass_sequence(
pp::panopainter::LegacyNodeStrokePreviewPassSequenceRequest {
@@ -817,7 +788,7 @@ void NodeStrokePreview::draw_stroke_immediate()
.capture_background = [&] {
execute_stroke_preview_background_capture_pass(
size,
b->m_tip_mix > 0.f || b->m_blend_mode != 0,
pass_orchestration.background_colorize,
m_tex_background,
[&] {
m_plane.draw_fill();
@@ -836,7 +807,7 @@ void NodeStrokePreview::draw_stroke_immediate()
m_tex,
m_rtt_mixer,
copy_stroke_destination,
preview_composite_plan.uses_mixer);
pass_orchestration.composite.uses_mixer);
},
.execute_main_pass = [&] {
execute_stroke_preview_live_pass(

View File

@@ -1,91 +1,104 @@
#pragma once
#include "renderer_api/renderer_api.h"
#include "util.h"
#include "../libs/glm/glm/glm.hpp"
#include <cstdint>
#include <map>
#include <string>
#include <sys/stat.h>
uint16_t constexpr shader_const_hash(const char* input)
{
return *input ?
static_cast<uint16_t>(*input) + 33 * shader_const_hash(input + 1) :
5381;
}
bool check_uniform_uniqueness();
enum class kShaderUniform : uint16_t
{
MVP = const_hash("mvp"),
Tex = const_hash("tex"),
TexFG = const_hash("tex_fg"),
TexBG = const_hash("tex_bg"),
TexMix = const_hash("tex_mix"),
TexMixA = const_hash("tex_mix_alpha"),
TexMask = const_hash("tex_mask"),
TexDual = const_hash("tex_dual"),
TexStroke = const_hash("tex_stroke"),
TexPattern = const_hash("tex_pattern"),
PatternOffset = const_hash("pattern_offset"),
PatternAlpha = const_hash("pattern_alpha"),
MixAlpha = const_hash("mix_alpha"),
Opacity = const_hash("opacity"),
Wet = const_hash("wet"),
Lock = const_hash("lock"),
Col = const_hash("col"),
Tof = const_hash("tof"),
Tsz = const_hash("tsz"),
Alpha = const_hash("alpha"),
Mask = const_hash("mask"),
Resolution = const_hash("resolution"),
Highlight = const_hash("highlight"),
BlendMode = const_hash("blend_mode"),
DualBlendMode = const_hash("dual_blend_mode"),
Noise = const_hash("noise"),
Direction = const_hash("dir"),
UseDual = const_hash("use_dual"),
UsePattern = const_hash("use_pattern"),
LightDir = const_hash("light_dir"),
Mode = const_hash("mode"),
Ambient = const_hash("ambient"),
PatternInvert = const_hash("pattern_invert"),
PatternScale = const_hash("pattern_scale"),
PatternBright = const_hash("pattern_bright"),
PatternContrast = const_hash("pattern_contr"),
PatternDepth = const_hash("pattern_depth"),
PatternBlendMode = const_hash("patt_blend_mode"),
Colorize = const_hash("colorize"),
DualAlpha = const_hash("dual_alpha"),
UseFragcoord = const_hash("use_fragcoord"),
DrawOutline = const_hash("draw_outline"),
MVP = shader_const_hash("mvp"),
Tex = shader_const_hash("tex"),
TexFG = shader_const_hash("tex_fg"),
TexBG = shader_const_hash("tex_bg"),
TexMix = shader_const_hash("tex_mix"),
TexMixA = shader_const_hash("tex_mix_alpha"),
TexMask = shader_const_hash("tex_mask"),
TexDual = shader_const_hash("tex_dual"),
TexStroke = shader_const_hash("tex_stroke"),
TexPattern = shader_const_hash("tex_pattern"),
PatternOffset = shader_const_hash("pattern_offset"),
PatternAlpha = shader_const_hash("pattern_alpha"),
MixAlpha = shader_const_hash("mix_alpha"),
Opacity = shader_const_hash("opacity"),
Wet = shader_const_hash("wet"),
Lock = shader_const_hash("lock"),
Col = shader_const_hash("col"),
Tof = shader_const_hash("tof"),
Tsz = shader_const_hash("tsz"),
Alpha = shader_const_hash("alpha"),
Mask = shader_const_hash("mask"),
Resolution = shader_const_hash("resolution"),
Highlight = shader_const_hash("highlight"),
BlendMode = shader_const_hash("blend_mode"),
DualBlendMode = shader_const_hash("dual_blend_mode"),
Noise = shader_const_hash("noise"),
Direction = shader_const_hash("dir"),
UseDual = shader_const_hash("use_dual"),
UsePattern = shader_const_hash("use_pattern"),
LightDir = shader_const_hash("light_dir"),
Mode = shader_const_hash("mode"),
Ambient = shader_const_hash("ambient"),
PatternInvert = shader_const_hash("pattern_invert"),
PatternScale = shader_const_hash("pattern_scale"),
PatternBright = shader_const_hash("pattern_bright"),
PatternContrast = shader_const_hash("pattern_contr"),
PatternDepth = shader_const_hash("pattern_depth"),
PatternBlendMode = shader_const_hash("patt_blend_mode"),
Colorize = shader_const_hash("colorize"),
DualAlpha = shader_const_hash("dual_alpha"),
UseFragcoord = shader_const_hash("use_fragcoord"),
DrawOutline = shader_const_hash("draw_outline"),
};
enum class kShader : uint16_t
{
Color = const_hash("color"),
ColorQuad = const_hash("color-quad"),
ColorTri = const_hash("color-tri"),
ColorHue = const_hash("color-hue"),
Texture = const_hash("texture"),
TextureMask = const_hash("texture-mask"),
TextureColorize = const_hash("texture-colorize"),
TextureAlpha= const_hash("texture-alpha"),
TextureBlend= const_hash("texture-blend"),
CompErase = const_hash("comp-erase"),
CompDraw = const_hash("comp-draw"),
UVs = const_hash("uvs"),
UVs_2 = const_hash("uvs2"),
Font = const_hash("font"),
Atlas = const_hash("atlas"),
Stroke = const_hash("stroke"),
StrokePad = const_hash("stroke-pad"),
StrokeDilate= const_hash("stroke-dilate"),
StrokePreview = const_hash("stroke-preview"),
Checkerboard= const_hash("checkerboard"),
Equirect = const_hash("equirect"),
BrushStroke = const_hash("brush-stroke"),
VertexColor = const_hash("vertex-color"),
Lambert = const_hash("lambert"),
LambertLightmap = const_hash("lambert-lightmap"),
BakeUV = const_hash("bakeuv"),
Color = shader_const_hash("color"),
ColorQuad = shader_const_hash("color-quad"),
ColorTri = shader_const_hash("color-tri"),
ColorHue = shader_const_hash("color-hue"),
Texture = shader_const_hash("texture"),
TextureMask = shader_const_hash("texture-mask"),
TextureColorize = shader_const_hash("texture-colorize"),
TextureAlpha= shader_const_hash("texture-alpha"),
TextureBlend= shader_const_hash("texture-blend"),
CompErase = shader_const_hash("comp-erase"),
CompDraw = shader_const_hash("comp-draw"),
UVs = shader_const_hash("uvs"),
UVs_2 = shader_const_hash("uvs2"),
Font = shader_const_hash("font"),
Atlas = shader_const_hash("atlas"),
Stroke = shader_const_hash("stroke"),
StrokePad = shader_const_hash("stroke-pad"),
StrokeDilate= shader_const_hash("stroke-dilate"),
StrokePreview = shader_const_hash("stroke-preview"),
Checkerboard= shader_const_hash("checkerboard"),
Equirect = shader_const_hash("equirect"),
BrushStroke = shader_const_hash("brush-stroke"),
VertexColor = shader_const_hash("vertex-color"),
Lambert = shader_const_hash("lambert"),
LambertLightmap = shader_const_hash("lambert-lightmap"),
BakeUV = shader_const_hash("bakeuv"),
};
class Shader
{
std::map<std::string, struct stat> m_deps;
std::string m_path;
std::map<kShaderUniform, GLuint> m_umap;
GLuint prog;
std::map<kShaderUniform, unsigned int> m_umap;
unsigned int prog;
std::string read(const std::string& path);
public:
kShader name;
@@ -102,7 +115,7 @@ public:
void u_int(kShaderUniform id, int i);
void u_int(const char* uniform_name, int i);
void u_float(kShaderUniform id, float f);
GLint GetAttribLocation(const char* attribute_name);
int GetAttribLocation(const char* attribute_name);
};
class ShaderManager

View File

@@ -1,5 +1,9 @@
#pragma once
#include <condition_variable>
#include <deque>
#include <mutex>
#ifdef _DEBUG
#define GL(stmt) stmt; check_OpenGLError(#stmt, __FILE__, __LINE__);
#else