策略抽离
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
#include "Explicit_Frame_Flow.h"
|
||||
#include "../../architecture/Render_Time.h"
|
||||
#include "../../architecture/Update_Completion.h"
|
||||
|
||||
namespace renderive {
|
||||
|
||||
namespace {
|
||||
struct Explicit_Render_Surface_Handle final : Render_Frame_Surface_Handle {
|
||||
explicit Explicit_Render_Surface_Handle(std::shared_ptr<Render_Output> output) : output(std::move(output)) {}
|
||||
std::shared_ptr<Render_Output> output;
|
||||
};
|
||||
|
||||
struct Explicit_Present_Surface_Handle final : Present_Surface_Handle {
|
||||
explicit Explicit_Present_Surface_Handle(std::shared_ptr<Render_Output> output) : output_value(std::move(output)) {}
|
||||
|
||||
[[nodiscard]] Render_Output* output() const override {
|
||||
return output_value.get();
|
||||
}
|
||||
|
||||
std::shared_ptr<Render_Output> output_value;
|
||||
};
|
||||
|
||||
Explicit_Render_Surface_Handle* explicit_handle(Render_Frame_Surface& surface) {
|
||||
return static_cast<Explicit_Render_Surface_Handle*>(surface.handle.get());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Explicit_Frame_Flow::Explicit_Frame_Flow()
|
||||
: pending_requests(memory_resource(Memory_Domain::Update_Completion)) {}
|
||||
|
||||
Render_Ticket Explicit_Frame_Flow::request_render() {
|
||||
auto state = make_update_state();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(request_mutex);
|
||||
pending_requests.push_back(state);
|
||||
}
|
||||
manual_request_pending.store(true, std::memory_order_release);
|
||||
return Render_Ticket(std::move(state));
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::attach(Frame_Flow_Host& host_value) {
|
||||
host = &host_value;
|
||||
}
|
||||
|
||||
Frame_Flow_Runtime_Snapshot Explicit_Frame_Flow::runtime_snapshot(std::uint64_t now_ns, bool destroying) const {
|
||||
return {
|
||||
destroying,
|
||||
manual_request_pending.load(std::memory_order_acquire),
|
||||
render_job_active.load(std::memory_order_acquire),
|
||||
frame_ready.load(std::memory_order_acquire),
|
||||
present_active.load(std::memory_order_acquire),
|
||||
now_ns
|
||||
};
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::advance_edit_version() {
|
||||
edit_version.fetch_add(1, std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::cancel_all_update_states() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(request_mutex);
|
||||
for (auto& state : pending_requests) {
|
||||
if (state)
|
||||
state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled);
|
||||
}
|
||||
pending_requests.clear();
|
||||
}
|
||||
std::shared_ptr<Render_Output> output;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(surface_mutex);
|
||||
output = std::move(present_surface);
|
||||
}
|
||||
if (output)
|
||||
cancel_update_states(output->presented_update_states);
|
||||
}
|
||||
|
||||
Render_Frame_Surface Explicit_Frame_Flow::begin_render_frame() {
|
||||
if (render_job_active.exchange(true, std::memory_order_acq_rel))
|
||||
return {};
|
||||
auto output = std::make_shared<Render_Output>();
|
||||
auto handle = std::make_unique<Explicit_Render_Surface_Handle>(output);
|
||||
auto* output_pointer = output.get();
|
||||
std::uint64_t input_version = edit_version.load(std::memory_order_acquire);
|
||||
return Render_Frame_Surface(output_pointer, input_version, std::move(handle));
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::cancel_render_frame(Render_Frame_Surface&& surface) {
|
||||
(void)surface;
|
||||
render_job_active.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::discard_render_frame(Render_Frame_Surface&& surface) {
|
||||
(void)surface;
|
||||
render_job_active.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
Render_Surface_Publish_Result Explicit_Frame_Flow::publish_rendered_frame(Render_Frame_Surface&& surface, std::uint64_t now_ns) {
|
||||
Render_Surface_Publish_Result result;
|
||||
auto* handle = explicit_handle(surface);
|
||||
if (!handle || !handle->output) {
|
||||
render_job_active.store(false, std::memory_order_release);
|
||||
return result;
|
||||
}
|
||||
if (handle->output->metadata) {
|
||||
handle->output->metadata->transition_12_ns = now_ns;
|
||||
handle->output->metadata->ready_queue_wait_ns = now_ns > handle->output->metadata->render_end_ns ? now_ns - handle->output->metadata->render_end_ns : 0;
|
||||
handle->output->metadata->update_request_id = ++next_present_request_id;
|
||||
handle->output->metadata->update_request_time_ns = now_ns;
|
||||
result.update_request_id = handle->output->metadata->update_request_id;
|
||||
result.update_request_time = now_ns;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(surface_mutex);
|
||||
present_surface = std::move(handle->output);
|
||||
}
|
||||
rendered_version = surface.input_version;
|
||||
frame_ready.store(true, std::memory_order_release);
|
||||
paint_request_pending.store(true, std::memory_order_release);
|
||||
render_job_active.store(false, std::memory_order_release);
|
||||
Size size = present_surface ? present_surface->image.size() : Size{};
|
||||
result.dirty_rect = Rect{0, 0, size.width, size.height};
|
||||
result.request_present = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
Render_Surface_Publish_Result Explicit_Frame_Flow::request_present(std::uint64_t now_ns) {
|
||||
Render_Surface_Publish_Result result;
|
||||
std::shared_ptr<Render_Output> output;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(surface_mutex);
|
||||
output = present_surface;
|
||||
}
|
||||
if (!output)
|
||||
return result;
|
||||
if (output->metadata) {
|
||||
output->metadata->update_request_id = ++next_present_request_id;
|
||||
output->metadata->update_request_time_ns = now_ns;
|
||||
result.update_request_id = output->metadata->update_request_id;
|
||||
result.update_request_time = now_ns;
|
||||
}
|
||||
paint_request_pending.store(true, std::memory_order_release);
|
||||
Size size = output->image.size();
|
||||
result.dirty_rect = Rect{0, 0, size.width, size.height};
|
||||
result.request_present = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
Present_Surface_Lease Explicit_Frame_Flow::begin_present(std::uint64_t now_ns, std::shared_ptr<Frame_Lifecycle_Record>& returned_frame_record) {
|
||||
returned_frame_record.reset();
|
||||
std::shared_ptr<Render_Output> output;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(surface_mutex);
|
||||
output = present_surface;
|
||||
}
|
||||
if (!output || present_active.exchange(true, std::memory_order_acq_rel))
|
||||
return {};
|
||||
bool is_new = frame_ready.exchange(false, std::memory_order_acq_rel);
|
||||
bool pending = paint_request_pending.exchange(false, std::memory_order_acq_rel);
|
||||
if (is_new && output->metadata) {
|
||||
output->metadata->transition_23_ns = now_ns;
|
||||
output->metadata->present_queue_wait_ns = now_ns > output->metadata->transition_12_ns ? now_ns - output->metadata->transition_12_ns : 0;
|
||||
}
|
||||
return Present_Surface_Lease_Access::from_handle(
|
||||
std::make_unique<Explicit_Present_Surface_Handle>(std::move(output)),
|
||||
is_new,
|
||||
pending);
|
||||
}
|
||||
|
||||
std::shared_ptr<Frame_Lifecycle_Record> Explicit_Frame_Flow::end_present(Present_Surface_Lease&& surface, std::uint64_t paint_begin_ns, std::uint64_t paint_end_ns) {
|
||||
std::shared_ptr<Frame_Lifecycle_Record> record;
|
||||
Render_Output* output = Present_Surface_Lease_Access::output(surface);
|
||||
if (output && surface.new_frame()) {
|
||||
record = output->metadata;
|
||||
if (record) {
|
||||
record->paint_begin_ns = paint_begin_ns;
|
||||
record->paint_end_ns = paint_end_ns;
|
||||
record->outcome = Frame_Outcome::Presented;
|
||||
}
|
||||
complete_update_states(output->presented_update_states, Update_Stage::Presented);
|
||||
}
|
||||
Present_Surface_Lease_Access::reset(surface);
|
||||
present_active.store(false, std::memory_order_release);
|
||||
return record;
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::activate_view(std::uint64_t now_ns) {
|
||||
active.store(true, std::memory_order_release);
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::deactivate_view() {
|
||||
active.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool Explicit_Frame_Flow::view_active() const {
|
||||
return active.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_model_dirty(std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_viewport_changed(Size, std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_render_finished(Frame_Lifecycle_Record&, std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_paint_finished(std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_frame_returned(Frame_Lifecycle_Record&, std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::notify_timer_fired(std::uint64_t now_ns) {
|
||||
evaluate(now_ns);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::drain_frame_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& output) {
|
||||
std::lock_guard<std::mutex> lock(request_mutex);
|
||||
for (auto& state : pending_requests)
|
||||
output.push_back(std::move(state));
|
||||
pending_requests.clear();
|
||||
manual_request_pending.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
Explicit_Diagnostics Explicit_Frame_Flow::explicit_diagnostics() const {
|
||||
std::lock_guard<std::mutex> lock(request_mutex);
|
||||
return Explicit_Diagnostics{
|
||||
active.load(std::memory_order_acquire),
|
||||
static_cast<std::uint64_t>(pending_requests.size())
|
||||
};
|
||||
}
|
||||
|
||||
Flow_Diagnostics Explicit_Frame_Flow::diagnostics() const {
|
||||
Explicit_Diagnostics typed = explicit_diagnostics();
|
||||
return Flow_Diagnostics{
|
||||
Common_Flow_Diagnostics{typed.active},
|
||||
typed
|
||||
};
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::shutdown() {
|
||||
host = nullptr;
|
||||
cancel_all_update_states();
|
||||
active.store(false, std::memory_order_release);
|
||||
manual_request_pending.store(false, std::memory_order_release);
|
||||
render_job_active.store(false, std::memory_order_release);
|
||||
frame_ready.store(false, std::memory_order_release);
|
||||
present_active.store(false, std::memory_order_release);
|
||||
paint_request_pending.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Explicit_Frame_Flow::evaluate(std::uint64_t now_ns) {
|
||||
if (!host)
|
||||
return;
|
||||
Frame_Flow_Runtime_Snapshot runtime = host->runtime_snapshot(now_ns);
|
||||
if (runtime.destroying)
|
||||
return;
|
||||
if (runtime.middle_has_new_frame && !runtime.paint_active)
|
||||
host->request_paint_from_middle();
|
||||
if (!manual_request_pending.load(std::memory_order_acquire))
|
||||
return;
|
||||
if (runtime.render_job_active)
|
||||
return;
|
||||
if (host->try_render_once())
|
||||
manual_request_pending.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
} // namespace renderive
|
||||
Reference in New Issue
Block a user