Add paint feedback strategy planner

This commit is contained in:
2026-06-03 17:58:24 +02:00
parent dc23a5648d
commit 94a6877e7c
8 changed files with 360 additions and 3 deletions

View File

@@ -335,6 +335,18 @@ struct PlanBrushStrokeControlArgs {
int blend_mode = 0;
};
struct PlanPaintFeedbackArgs {
int width = 64;
int height = 32;
bool complex_blend = true;
bool framebuffer_fetch = false;
bool explicit_texture_transitions = false;
bool texture_copy = false;
bool render_target_blit = false;
bool render_only_target = false;
bool depth_target = false;
};
struct PlanGridOperationArgs {
std::string kind = "pick";
std::string path;
@@ -1753,6 +1765,7 @@ void print_help()
<< " plan-brush-operation --kind color|tip|pattern|dual|preset|settings [--path FILE] [--thumb FILE] [--r N] [--g N] [--b N] [--a N] [--no-brush]\n"
<< " plan-brush-texture-list --kind add|remove|move [--dir NAME] [--data-path DIR] [--source FILE] [--item-count N] [--current-index N] [--offset N] [--user-texture]\n"
<< " plan-brush-stroke-control --kind float|bool|blend|tip-aspect-reset|default-reset [--setting NAME] [--value N] [--enabled|--disabled] [--blend-mode N]\n"
<< " plan-paint-feedback [--width N] [--height N] [--simple|--complex] [--framebuffer-fetch] [--texture-copy] [--blit] [--explicit-transitions] [--render-only] [--depth]\n"
<< " plan-canvas-tool --kind draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket|pick|touch-lock [--current-mode-draw]\n"
<< " plan-canvas-tool-state [--mode draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket] [--picking] [--touch-lock]\n"
<< " plan-grid-operation --kind pick|load|reload|clear|render|commit [--path FILE] [--no-heightmap] [--no-canvas] [--float32] [--float16] [--texture-resolution N] [--samples N]\n"
@@ -4809,6 +4822,117 @@ int plan_brush_stroke_control(int argc, char** argv)
return 0;
}
pp::foundation::Status parse_plan_paint_feedback_args(
int argc,
char** argv,
PlanPaintFeedbackArgs& args)
{
for (int i = 2; i < argc; ++i) {
const std::string_view key(argv[i]);
if (key == "--width" || key == "--height") {
if (i + 1 >= argc) {
return pp::foundation::Status::invalid_argument("missing value for option");
}
const auto value = parse_i32_arg(argv[++i]);
if (!value) {
return value.status();
}
if (value.value() <= 0) {
return pp::foundation::Status::invalid_argument("paint feedback extent must be greater than zero");
}
if (key == "--width") {
args.width = value.value();
} else {
args.height = value.value();
}
} else if (key == "--simple") {
args.complex_blend = false;
} else if (key == "--complex") {
args.complex_blend = true;
} else if (key == "--framebuffer-fetch") {
args.framebuffer_fetch = true;
} else if (key == "--explicit-transitions") {
args.explicit_texture_transitions = true;
} else if (key == "--texture-copy") {
args.texture_copy = true;
} else if (key == "--blit") {
args.render_target_blit = true;
} else if (key == "--render-only") {
args.render_only_target = true;
} else if (key == "--depth") {
args.depth_target = true;
} else {
return pp::foundation::Status::invalid_argument("unknown option");
}
}
return pp::foundation::Status::success();
}
int plan_paint_feedback(int argc, char** argv)
{
PlanPaintFeedbackArgs args;
const auto status = parse_plan_paint_feedback_args(argc, argv, args);
if (!status.ok()) {
print_error("plan-paint-feedback", status.message);
return 2;
}
pp::renderer::TextureUsage usage = pp::renderer::TextureUsage::render_target;
if (!args.render_only_target) {
usage |= pp::renderer::TextureUsage::sampled;
usage |= pp::renderer::TextureUsage::copy_source;
usage |= pp::renderer::TextureUsage::copy_destination;
}
const pp::renderer::RenderDeviceFeatures features {
.framebuffer_fetch = args.framebuffer_fetch,
.explicit_texture_transitions = args.explicit_texture_transitions,
.texture_copy = args.texture_copy,
.render_target_blit = args.render_target_blit,
};
const pp::renderer::TextureDesc target {
.extent = pp::renderer::Extent2D {
.width = static_cast<std::uint32_t>(args.width),
.height = static_cast<std::uint32_t>(args.height),
},
.format = args.depth_target
? pp::renderer::TextureFormat::depth24_stencil8
: pp::renderer::TextureFormat::rgba8,
.usage = usage,
.debug_name = "paint-feedback-target",
};
const auto plan = pp::renderer::plan_paint_feedback(features, target, args.complex_blend);
if (!plan) {
print_error("plan-paint-feedback", plan.status().message);
return 2;
}
const auto& value = plan.value();
std::cout << "{\"ok\":true,\"command\":\"plan-paint-feedback\""
<< ",\"state\":{\"width\":" << args.width
<< ",\"height\":" << args.height
<< ",\"complexBlend\":" << json_bool(args.complex_blend)
<< ",\"framebufferFetch\":" << json_bool(args.framebuffer_fetch)
<< ",\"explicitTransitions\":" << json_bool(args.explicit_texture_transitions)
<< ",\"textureCopy\":" << json_bool(args.texture_copy)
<< ",\"blit\":" << json_bool(args.render_target_blit)
<< ",\"renderOnlyTarget\":" << json_bool(args.render_only_target)
<< ",\"depthTarget\":" << json_bool(args.depth_target)
<< "},\"plan\":{\"path\":\"" << pp::renderer::paint_feedback_path_name(value.path)
<< "\",\"targetFormat\":\"" << pp::renderer::texture_format_name(value.target_desc.format)
<< "\",\"targetBytes\":" << value.target_bytes
<< ",\"complexBlend\":" << json_bool(value.complex_blend)
<< ",\"readsDestinationColor\":" << json_bool(value.reads_destination_color)
<< ",\"requiresAuxiliaryTexture\":" << json_bool(value.requires_auxiliary_texture)
<< ",\"requiresTextureCopy\":" << json_bool(value.requires_texture_copy)
<< ",\"requiresRenderTargetBlit\":" << json_bool(value.requires_render_target_blit)
<< ",\"requiresExplicitTransition\":" << json_bool(value.requires_explicit_transition)
<< "}}\n";
return 0;
}
pp::foundation::Status parse_plan_canvas_tool_args(
int argc,
char** argv,
@@ -7939,6 +8063,10 @@ int main(int argc, char** argv)
return plan_brush_stroke_control(argc, argv);
}
if (command == "plan-paint-feedback") {
return plan_paint_feedback(argc, argv);
}
if (command == "plan-canvas-tool") {
return plan_canvas_tool(argc, argv);
}