仍然闪烁
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user