仍然闪烁

This commit is contained in:
2026-08-02 19:26:50 +08:00
parent 9a39f88427
commit 36d63efc7b
10 changed files with 650 additions and 128 deletions
+67 -23
View File
@@ -19,6 +19,7 @@
#include "../base/Memory.h"
#include "../base/global.h"
#include "../render/Canvas.h"
#include "../render/Frame_Prepare_Subflow.h"
#include "../render/Image.h"
#include "../render/Render_Frame_Snapshot.h"
#include "Psc_Cpp_Core/Base/RingBuffer.hpp"
@@ -143,15 +144,25 @@ struct Waterfall_Image_Tile {
Image image;
};
struct Waterfall_Image_Job {
explicit Waterfall_Image_Job(std::shared_ptr<Waterfall_Image_Request> request, int columns, int rows)
: request(std::move(request)), tile_columns(columns), tile_rows(rows), remaining(columns * rows) {
explicit Waterfall_Image_Job(std::shared_ptr<const Waterfall_Image_Request> request, int columns, int rows)
: request(std::move(request)),
update_states(memory_resource(Memory_Domain::Update_Completion)),
tile_columns(columns),
tile_rows(rows) {
tiles.resize(static_cast<std::size_t>(columns * rows));
}
std::shared_ptr<Waterfall_Image_Request> request;
~Waterfall_Image_Job() {
for (auto& state : update_states) {
if (state)
state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled);
}
update_states.clear();
}
std::shared_ptr<const Waterfall_Image_Request> request;
std::pmr::vector<std::shared_ptr<Update_State>> update_states;
int tile_columns{};
int tile_rows{};
std::vector<Waterfall_Image_Tile> tiles;
std::atomic<int> remaining;
};
static void complete_waterfall_request_states(Waterfall_Image_Request& request, std::error_code error, Update_Outcome outcome) {
for (auto& state : request.update_states) {
@@ -186,6 +197,19 @@ static int waterfall_tile_row_count(int height) {
static constexpr int Tile_Height = 64;
return std::max(1, (height + Tile_Height - 1) / Tile_Height);
}
static std::shared_ptr<Waterfall_Image_Job> create_waterfall_image_job(std::shared_ptr<Waterfall_Image_Request> request) {
if (!request || request->key.width <= 0 || request->key.height <= 0)
return {};
int columns = waterfall_tile_column_count(request->key.width);
int rows = waterfall_tile_row_count(request->key.height);
std::pmr::vector<std::shared_ptr<Update_State>> update_states = std::move(request->update_states);
auto job = std::make_shared<Waterfall_Image_Job>(
std::shared_ptr<const Waterfall_Image_Request>(std::move(request)),
columns,
rows);
job->update_states = std::move(update_states);
return job;
}
static void write_waterfall_tile(Waterfall_Image_Job& job, int tile_index) {
const Waterfall_Image_Request& request = *job.request;
int tile_x = tile_index % job.tile_columns;
@@ -222,25 +246,15 @@ static void write_waterfall_tile(Waterfall_Image_Job& job, int tile_index) {
}
}
}
static void write_waterfall_tiles(Waterfall_Image_Job& job) {
int tile_count = static_cast<int>(job.tiles.size());
for (int tile_index = 0; tile_index < tile_count; ++tile_index)
write_waterfall_tile(job, tile_index);
}
static Waterfall_Image_Snapshot build_waterfall_image_snapshot(const std::shared_ptr<Waterfall_Image_Request>& request_ptr) {
Waterfall_Image_Request& request = *request_ptr;
Waterfall_Image_Job job(
request_ptr,
waterfall_tile_column_count(request.key.width),
waterfall_tile_row_count(request.key.height));
write_waterfall_tiles(job);
static Waterfall_Image_Snapshot compose_waterfall_image(Waterfall_Image_Job& job) {
const Waterfall_Image_Request& request = *job.request;
Waterfall_Image_Snapshot snapshot;
snapshot.key = request.key;
snapshot.frequency_range = request.draw_frequency_range;
snapshot.time_range = request.draw_time_range;
snapshot.source_rect = request.draw_source_rect;
snapshot.image.resize(request.key.width, request.key.height);
for (const auto& tile : job.tiles) {
for (const Waterfall_Image_Tile& tile : job.tiles) {
for (int y = 0; y < tile.image.height(); ++y) {
Pixel* target = snapshot.image.row(tile.y + y);
const Pixel* source = tile.image.row(y);
@@ -248,10 +262,10 @@ static Waterfall_Image_Snapshot build_waterfall_image_snapshot(const std::shared
std::memcpy(target + tile.x, source, static_cast<std::size_t>(tile.image.width()) * sizeof(Pixel));
}
}
snapshot.update_states = std::move(request.update_states);
snapshot.update_states = std::move(job.update_states);
return snapshot;
}
struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State, Waterfall_Input_Data>, Hit_Testable, Hover_Interactive {
struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State, Waterfall_Input_Data>, Hit_Testable, Hover_Interactive, Frame_Prepare_Subtask_Source {
static constexpr std::size_t Row_Queue_Capacity = 256;
Waterfall_Ring_Buffer ring_buffer;
std::weak_ptr<Color_Bar> color_bar;
@@ -357,6 +371,13 @@ struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State,
return true;
}
void prepare_data(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) override {
prepare_waterfall(snapshot, frame_view, nullptr);
}
bool build_prepare_subtasks(Render_Task_Subflow& subflow, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) override {
prepare_waterfall(snapshot, frame_view, &subflow);
return true;
}
void prepare_waterfall(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view, Render_Task_Subflow* subflow) {
Waterfall_Render_State* s = render_state(frame_view);
if (!s)
return;
@@ -424,9 +445,9 @@ struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State,
break;
}
}
update_image_item(snapshot, *timeline, s);
update_image_item(snapshot, *timeline, s, subflow);
}
void update_image_item(const Render_Frame_Snapshot& snapshot, const Timeline_Stream_Snapshot& timeline, Waterfall_Render_State* s) {
void update_image_item(const Render_Frame_Snapshot& snapshot, const Timeline_Stream_Snapshot& timeline, Waterfall_Render_State* s, Render_Task_Subflow* subflow) {
if (!s)
return;
auto frequency_axis = s->frequency_axis.lock();
@@ -469,7 +490,8 @@ struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State,
};
bool should_submit = !submitted_image_key || !(*submitted_image_key == key) || !pending_image_update_states.empty();
if (should_submit) {
submitted_image_key = key;
if (!subflow)
return;
auto request = std::make_shared<Waterfall_Image_Request>();
request->key = key;
request->color_map = color_scale->color_map;
@@ -497,7 +519,29 @@ struct Waterfall_Private : Typed_Render_Data<Waterfall, Waterfall_Render_State,
}
request->update_states = std::move(pending_image_update_states);
pending_image_update_states = std::pmr::vector<std::shared_ptr<Update_State>>(memory_resource(Memory_Domain::Update_Completion));
image_snapshot = build_waterfall_image_snapshot(request);
auto job = create_waterfall_image_job(std::move(request));
if (!job || job->tiles.empty())
return;
std::vector<Render_Task_Graph_Node> tile_tasks;
tile_tasks.reserve(job->tiles.size());
for (std::size_t i = 0; i < job->tiles.size(); ++i) {
tile_tasks.push_back(subflow->emplace(Render_Task_Kind::Waterfall, Task([job, i]() {
write_waterfall_tile(*job, static_cast<int>(i));
})));
}
auto compose = subflow->emplace(Render_Task_Kind::Compose, Task([this, job]() {
if (q() && q()->get_retiring())
return;
Waterfall_Image_Snapshot result = compose_waterfall_image(*job);
if (q() && q()->get_retiring()) {
complete_waterfall_result_states(result, std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled);
return;
}
image_snapshot = std::move(result);
submitted_image_key = image_snapshot->key;
}));
for (auto tile : tile_tasks)
subflow->precede(tile, compose);
}
}
void draw_image(Canvas& canvas, const Render_Frame_Snapshot& snapshot, Waterfall_Render_State* s, Abs_Axis* h_axis, Time_Axis* v_axis) {