Add paint feedback strategy planner
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -132,6 +132,12 @@ enum class BlitFilter : std::uint8_t {
|
||||
linear,
|
||||
};
|
||||
|
||||
enum class PaintFeedbackPath : std::uint8_t {
|
||||
none,
|
||||
framebuffer_fetch,
|
||||
ping_pong_textures,
|
||||
};
|
||||
|
||||
enum class BlendFactor : std::uint8_t {
|
||||
zero,
|
||||
one,
|
||||
@@ -236,6 +242,19 @@ struct RenderDeviceFeatures {
|
||||
bool float32_render_targets = false;
|
||||
};
|
||||
|
||||
struct PaintFeedbackPlan {
|
||||
PaintFeedbackPath path = PaintFeedbackPath::none;
|
||||
TextureDesc target_desc {};
|
||||
TextureDesc auxiliary_desc {};
|
||||
std::uint64_t target_bytes = 0;
|
||||
bool complex_blend = false;
|
||||
bool reads_destination_color = false;
|
||||
bool requires_auxiliary_texture = false;
|
||||
bool requires_texture_copy = false;
|
||||
bool requires_render_target_blit = false;
|
||||
bool requires_explicit_transition = false;
|
||||
};
|
||||
|
||||
class ITexture2D {
|
||||
public:
|
||||
virtual ~ITexture2D() = default;
|
||||
@@ -393,10 +412,15 @@ public:
|
||||
[[nodiscard]] pp::foundation::Status validate_blit_descs(
|
||||
TextureDesc source,
|
||||
TextureDesc destination) noexcept;
|
||||
[[nodiscard]] pp::foundation::Result<PaintFeedbackPlan> plan_paint_feedback(
|
||||
RenderDeviceFeatures features,
|
||||
TextureDesc target_desc,
|
||||
bool complex_blend) noexcept;
|
||||
[[nodiscard]] const char* texture_format_name(TextureFormat format) noexcept;
|
||||
[[nodiscard]] const char* texture_state_name(TextureState state) noexcept;
|
||||
[[nodiscard]] const char* primitive_topology_name(PrimitiveTopology topology) noexcept;
|
||||
[[nodiscard]] const char* blit_filter_name(BlitFilter filter) noexcept;
|
||||
[[nodiscard]] const char* paint_feedback_path_name(PaintFeedbackPath path) noexcept;
|
||||
[[nodiscard]] const char* blend_factor_name(BlendFactor factor) noexcept;
|
||||
[[nodiscard]] const char* blend_op_name(BlendOp op) noexcept;
|
||||
[[nodiscard]] const char* compare_op_name(CompareOp op) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user