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

@@ -823,6 +823,65 @@ pp::foundation::Status validate_blit_descs(TextureDesc source, TextureDesc desti
return pp::foundation::Status::success();
}
pp::foundation::Result<PaintFeedbackPlan> plan_paint_feedback(
RenderDeviceFeatures features,
TextureDesc target_desc,
bool complex_blend) noexcept
{
const auto target_status = validate_texture_desc(target_desc);
if (!target_status.ok()) {
return pp::foundation::Result<PaintFeedbackPlan>::failure(target_status);
}
if (!has_texture_usage(target_desc.usage, TextureUsage::render_target)) {
return pp::foundation::Result<PaintFeedbackPlan>::failure(
pp::foundation::Status::invalid_argument("paint feedback target must allow render_target usage"));
}
if (target_desc.format == TextureFormat::depth24_stencil8) {
return pp::foundation::Result<PaintFeedbackPlan>::failure(
pp::foundation::Status::invalid_argument("paint feedback target must be a color texture"));
}
const auto target_bytes = texture_byte_size(target_desc);
if (!target_bytes.ok()) {
return pp::foundation::Result<PaintFeedbackPlan>::failure(target_bytes.status());
}
PaintFeedbackPlan plan;
plan.target_desc = target_desc;
plan.target_bytes = target_bytes.value();
plan.complex_blend = complex_blend;
if (!complex_blend) {
return pp::foundation::Result<PaintFeedbackPlan>::success(plan);
}
plan.reads_destination_color = true;
if (features.framebuffer_fetch) {
plan.path = PaintFeedbackPath::framebuffer_fetch;
plan.requires_explicit_transition = features.explicit_texture_transitions;
return pp::foundation::Result<PaintFeedbackPlan>::success(plan);
}
const bool can_ping_pong = has_texture_usage(target_desc.usage, TextureUsage::sampled)
&& has_texture_usage(target_desc.usage, TextureUsage::copy_source)
&& has_texture_usage(target_desc.usage, TextureUsage::copy_destination)
&& (features.texture_copy || features.render_target_blit);
if (!can_ping_pong) {
return pp::foundation::Result<PaintFeedbackPlan>::failure(
pp::foundation::Status::invalid_argument(
"complex paint feedback requires framebuffer fetch or sampled copy-capable render targets"));
}
plan.path = PaintFeedbackPath::ping_pong_textures;
plan.requires_auxiliary_texture = true;
plan.requires_texture_copy = features.texture_copy;
plan.requires_render_target_blit = !features.texture_copy && features.render_target_blit;
plan.requires_explicit_transition = features.explicit_texture_transitions;
plan.auxiliary_desc = target_desc;
return pp::foundation::Result<PaintFeedbackPlan>::success(plan);
}
const char* texture_format_name(TextureFormat format) noexcept
{
switch (format) {
@@ -887,6 +946,20 @@ const char* blit_filter_name(BlitFilter filter) noexcept
return "unknown";
}
const char* paint_feedback_path_name(PaintFeedbackPath path) noexcept
{
switch (path) {
case PaintFeedbackPath::none:
return "none";
case PaintFeedbackPath::framebuffer_fetch:
return "framebuffer_fetch";
case PaintFeedbackPath::ping_pong_textures:
return "ping_pong_textures";
}
return "unknown";
}
const char* blend_factor_name(BlendFactor factor) noexcept
{
switch (factor) {