From ebb1a07857fe25fdaa66b2f86303bc8fbd621cfe Mon Sep 17 00:00:00 2001 From: skal Date: Tue, 10 Feb 2026 13:56:06 +0100 Subject: fix: Capture scene framebuffer before post-processing for CNN effect CNNEffect's "original" input was black because FadeEffect (priority 1) ran before CNNEffect (priority 1), fading the scene. Changed framebuffer capture to use framebuffer_a (scene output) instead of current_input (post-chain). Also add seq_compiler validation to detect post-process priority collisions within and across concurrent sequences, preventing similar render order issues. Updated stub_types.h WGPULoadOp enum values to match webgpu.h spec. Co-Authored-By: Claude Sonnet 4.5 --- tools/seq_compiler.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'tools/seq_compiler.cc') diff --git a/tools/seq_compiler.cc b/tools/seq_compiler.cc index fad2d88..ecb9908 100644 --- a/tools/seq_compiler.cc +++ b/tools/seq_compiler.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,25 @@ parse_parameters(const std::string& args) { return params; } +// Check if an effect is a post-process effect +bool is_post_process_effect(const std::string& class_name) { + // List of known post-process effects + static const std::vector post_process_effects = { + "FadeEffect", + "FlashEffect", + "GaussianBlurEffect", + "SolarizeEffect", + "VignetteEffect", + "ChromaAberrationEffect", + "DistortEffect", + "ThemeModulationEffect", + "CNNEffect", + "PassthroughEffect", + "CircleMaskEffect"}; + return std::find(post_process_effects.begin(), post_process_effects.end(), + class_name) != post_process_effects.end(); +} + // Calculate adaptive tick interval based on timeline duration int calculate_tick_interval(float max_time) { if (max_time <= 5) @@ -882,6 +902,76 @@ int main(int argc, char* argv[]) { }); } + // Validate: detect priority collisions among post-process effects + for (size_t seq_idx = 0; seq_idx < sequences.size(); ++seq_idx) { + const auto& seq = sequences[seq_idx]; + std::map> priority_map; + + // Group post-process effects by priority + for (const auto& eff : seq.effects) { + if (is_post_process_effect(eff.class_name)) { + int prio = std::stoi(eff.priority); + priority_map[prio].push_back(eff.class_name); + } + } + + // Check for collisions + for (const auto& [prio, effects] : priority_map) { + if (effects.size() > 1) { + std::cerr << "Warning: Priority collision detected in sequence at time " + << seq.start_time << "s\n"; + std::cerr << " Multiple post-process effects have priority " << prio + << ":\n"; + for (const auto& effect : effects) { + std::cerr << " - " << effect << "\n"; + } + std::cerr << " This may cause unexpected render order. Consider " + "adjusting priorities.\n"; + } + } + } + + // Validate: detect cross-sequence priority collisions for concurrent sequences + std::map> time_groups; + for (size_t i = 0; i < sequences.size(); ++i) { + time_groups[sequences[i].start_time].push_back(i); + } + + for (const auto& [start_time, seq_indices] : time_groups) { + if (seq_indices.size() > 1) { + // Multiple sequences start at the same time + std::map>> cross_priority_map; + + for (size_t seq_idx : seq_indices) { + const auto& seq = sequences[seq_idx]; + for (const auto& eff : seq.effects) { + if (is_post_process_effect(eff.class_name)) { + int prio = std::stoi(eff.priority); + cross_priority_map[prio].push_back({eff.class_name, seq_idx}); + } + } + } + + // Check for cross-sequence collisions + for (const auto& [prio, effects] : cross_priority_map) { + if (effects.size() > 1) { + std::cerr << "Warning: Cross-sequence priority collision at time " + << start_time << "s\n"; + std::cerr << " Multiple post-process effects across sequences have " + "priority " + << prio << ":\n"; + for (const auto& [effect, seq_idx] : effects) { + std::cerr << " - " << effect << " (sequence #" << seq_idx << ")\n"; + } + std::cerr << " Post-process effects from different sequences at the " + "same time will be\n"; + std::cerr << " merged into a single render chain. Consider adjusting " + "priorities to clarify order.\n"; + } + } + } + } + // Generate C++ code if output file is specified if (!output_cc.empty()) { std::ofstream out_file(output_cc); -- cgit v1.2.3