Files
Renderive/YSGraphic_Core/architecture/Render_Lease.h
T
2026-07-24 10:54:44 +08:00

165 lines
6.7 KiB
C++

#pragma once
#include <concepts>
#include <type_traits>
#include <utility>
#include "Renderable_Core.h"
namespace YSG {
template <typename T>
concept Render_State_Type = std::derived_from<T, Render_State> && std::is_copy_assignable_v<T>;
template <typename T>
concept Input_Data_Type = std::derived_from<T, Input_Data>;
template <typename T>
concept Render_Data_Type = std::derived_from<T, Render_Data>;
template <Render_Data_Type Base, typename Owner, Render_State_Type State, Input_Data_Type Input>
struct Typed_Render_Data_Base : Base {
Owner* q() {
return reinterpret_cast<Owner*>(this->qPtr);
}
State* render_state() override {
return reinterpret_cast<State*>(this->state(State_Render));
}
State* ready_state() override {
return reinterpret_cast<State*>(this->state(State_Ready));
}
State* edit_state() override {
return reinterpret_cast<State*>(this->state(State_Edit));
}
Input* render_input_data() override {
return reinterpret_cast<Input*>(this->input_data(Input_Render));
}
Input* edit_input_data() override {
return reinterpret_cast<Input*>(this->input_data(Input_Edit));
}
State* state_data(SRC src) {
return reinterpret_cast<State*>(this->state(src));
}
State* state_data_by_index(std::uint8_t index) {
return reinterpret_cast<State*>(this->state_by_index(index));
}
Input* input_data_by_index(std::uint8_t index) {
return reinterpret_cast<Input*>(Base::input_data_by_index(index));
}
template <typename Field>
Field state_value(Field State::* field, SRC src) {
return state_data(src)->*field;
}
template <typename Field>
void set_state_value(Field State::* field, Field value) {
auto lease = this->mStateControl.wait_mark_use_role(State_Edit);
auto state = state_data_by_index(lease.index);
Render_Edit_Guard guard(this, lease);
state->*field = std::move(value);
}
void sync_state_pipeline() override {
Triple_Buffer_Lease editLease = this->mStateControl.wait_mark_use_role(State_Edit);
Triple_Buffer_Lease readyLease = this->mStateControl.wait_mark_use_role(State_Ready);
auto ready = reinterpret_cast<State*>(this->state_by_index(readyLease.index));
auto edit = reinterpret_cast<State*>(this->state_by_index(editLease.index));
if (buffer_version_newer(edit->version, ready->version))
*ready = *edit;
this->mStateControl.unmark_use(readyLease);
this->mStateControl.unmark_use(editLease);
this->mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) {
auto ready = reinterpret_cast<State*>(this->state_by_index(view[State_Ready]));
auto render = reinterpret_cast<State*>(this->state_by_index(view[State_Render]));
return buffer_version_newer(ready->version, render->version);
});
this->mInputControl.wait_swap_role(Input_Edit, Input_Ready, [this](const Triple_Buffer_View& view) {
const Input_Buffer_Slot& edit = this->input_slot_by_index(view[Input_Edit]);
const Input_Buffer_Slot& ready = this->input_slot_by_index(view[Input_Ready]);
return edit.pending && buffer_version_newer(edit.version, ready.version);
});
this->mInputControl.wait_swap_role(Input_Ready, Input_Render, [this](const Triple_Buffer_View& view) {
const Input_Buffer_Slot& ready = this->input_slot_by_index(view[Input_Ready]);
const Input_Buffer_Slot& render = this->input_slot_by_index(view[Input_Render]);
return ready.pending && buffer_version_newer(ready.version, render.version);
});
if (!this->mRenderStart)
this->mRenderStart = true;
}
};
template <typename Owner, Render_State_Type State, Input_Data_Type Input>
using Typed_Render_Data = Typed_Render_Data_Base<Render_Data, Owner, State, Input>;
template <typename Owner, Render_Data_Type Data, Render_State_Type State, Input_Data_Type Input>
struct Renderable_Binding {
static void init(Owner* owner, const char* name) {
owner->dPtr = new Data;
owner->mObjectName = name;
}
static Data* d(Owner* owner) {
return reinterpret_cast<Data*>(owner->dPtr);
}
static Render_Data* create_render_data() {
return new Data;
}
static Render_State* create_render_state() {
return new State;
}
static Input_Data* create_input_data() {
return new Input;
}
};
template <Render_Data_Type Data, Render_State_Type State>
struct Render_State_Lease {
explicit Render_State_Lease(Data* data) : data(data), lease(data->mStateControl.wait_mark_use_role(State_Edit)), state(reinterpret_cast<State*>(data->state_by_index(lease.index))) {
}
Render_State_Lease(const Render_State_Lease&) = delete;
Render_State_Lease& operator=(const Render_State_Lease&) = delete;
~Render_State_Lease() {
data->unmark_state(lease);
}
State* operator->() {
return state;
}
State& operator*() {
return *state;
}
Data* data{};
Triple_Buffer_Lease lease{};
State* state{};
};
template <Render_Data_Type Data, Render_State_Type State>
struct Render_Edit_Lease {
explicit Render_Edit_Lease(Data* data) : data(data), lease(data->mStateControl.wait_mark_use_role(State_Edit)), state(reinterpret_cast<State*>(data->state_by_index(lease.index))) {
}
Render_Edit_Lease(const Render_Edit_Lease&) = delete;
Render_Edit_Lease& operator=(const Render_Edit_Lease&) = delete;
~Render_Edit_Lease() {
++data->state_by_index(lease.index)->version;
if (data->qPtr)
data->qPtr->mark_render_dirty();
data->unmark_state(lease);
}
State* operator->() {
return state;
}
State& operator*() {
return *state;
}
Data* data{};
Triple_Buffer_Lease lease{};
State* state{};
};
template <Render_Data_Type Data, Input_Data_Type Input>
struct Render_Input_Lease {
explicit Render_Input_Lease(Data* data, bool notify_render = true) : data(data), notify_render(notify_render), lease(data->mInputControl.wait_mark_use_role(Input_Edit)), input(reinterpret_cast<Input*>(data->input_data_by_index(lease.index))) {
}
Render_Input_Lease(const Render_Input_Lease&) = delete;
Render_Input_Lease& operator=(const Render_Input_Lease&) = delete;
~Render_Input_Lease() {
data->mark_input_dirty(lease, notify_render);
data->mInputControl.unmark_use(lease);
}
Input* operator->() {
return input;
}
Input& operator*() {
return *input;
}
Data* data{};
bool notify_render{};
Triple_Buffer_Lease lease{};
Input* input{};
};
} // namespace YSG