3D 优化
This commit is contained in:
@@ -52,7 +52,7 @@ struct Frame_Policy_Event {
|
||||
* 任意线程只向 MPMC 事件流提交事实;Plot tick consumer 是唯一归并写者。
|
||||
* 查询方只读取 current State,不参与事件归并,也不获取 Plot/Scene 锁。
|
||||
*/
|
||||
struct Frame_Policy final : double_buffer::Def<
|
||||
struct Frame_Policy : double_buffer::Def<
|
||||
Frame_Policy, double_buffer::Root,
|
||||
double_buffer::Mpmc_Triple_Buffer<
|
||||
detail::Frame_Policy_Event_Stream, detail::Frame_Policy_Event>> {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "Frame_Policy_3D.hpp"
|
||||
#include <algorithm>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
namespace aethera {
|
||||
void Frame_Policy_3D::submit_3d(detail::Frame_Policy_3D_Event event) {
|
||||
submit_stream<detail::Frame_Policy_3D_Event_Stream>(std::move(event));
|
||||
}
|
||||
|
||||
void Frame_Policy_3D::record_gpu_submitted(
|
||||
std::uint64_t sequence, bool overlaps_gpu) {
|
||||
submit_3d({detail::Frame_Policy_3D_Event_Type::submitted,
|
||||
sequence, overlaps_gpu});
|
||||
}
|
||||
|
||||
void Frame_Policy_3D::record_gpu_completed(std::uint64_t sequence) {
|
||||
submit_3d({detail::Frame_Policy_3D_Event_Type::completed, sequence});
|
||||
}
|
||||
|
||||
void Frame_Policy_3D::reset_3d_statistics() {
|
||||
submit_3d({detail::Frame_Policy_3D_Event_Type::reset});
|
||||
}
|
||||
|
||||
bool Frame_Policy_3D::consume_3d_events() {
|
||||
exchange_stream<detail::Frame_Policy_3D_Event_Stream>();
|
||||
bool consumed{};
|
||||
auto& state = static_cast<State&>(
|
||||
double_buffer::detail::Internal_Access::pending_state(this));
|
||||
access_rendering_stream<detail::Frame_Policy_3D_Event_Stream>(
|
||||
[&](std::span<detail::Frame_Policy_3D_Event> events) {
|
||||
for (const auto& event : events) {
|
||||
consumed = true;
|
||||
switch (event.type) {
|
||||
case detail::Frame_Policy_3D_Event_Type::submitted:
|
||||
++state.gpu_submission_count;
|
||||
++state.gpu_in_flight;
|
||||
state.peak_gpu_in_flight = std::max(
|
||||
state.peak_gpu_in_flight, state.gpu_in_flight);
|
||||
state.last_submitted_sequence = event.sequence;
|
||||
if (event.overlaps_gpu)
|
||||
++state.overlapped_release_count;
|
||||
else
|
||||
++state.completion_gated_release_count;
|
||||
break;
|
||||
case detail::Frame_Policy_3D_Event_Type::completed:
|
||||
++state.gpu_completion_count;
|
||||
if (state.gpu_in_flight != 0) --state.gpu_in_flight;
|
||||
state.last_completed_sequence = event.sequence;
|
||||
break;
|
||||
case detail::Frame_Policy_3D_Event_Type::reset: {
|
||||
const auto in_flight = state.gpu_in_flight;
|
||||
state = {};
|
||||
state.pipeline_capacity = 3;
|
||||
state.gpu_in_flight = in_flight;
|
||||
state.peak_gpu_in_flight = in_flight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (consumed) publish_state<Base_Tag>();
|
||||
return consumed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "Frame_Policy.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace aethera {
|
||||
namespace detail {
|
||||
struct Frame_Policy_3D_Event_Stream;
|
||||
enum struct Frame_Policy_3D_Event_Type : std::uint8_t {
|
||||
submitted,
|
||||
completed,
|
||||
reset
|
||||
};
|
||||
struct Frame_Policy_3D_Event {
|
||||
Frame_Policy_3D_Event_Type type{};
|
||||
std::uint64_t sequence{};
|
||||
bool overlaps_gpu{};
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* 3D 策略是 Frame_Policy 的独立状态层。它复用公共请求/吞吐事实,但不改变
|
||||
* 2D Frame_Policy 的默认模式和完成释放语义。GPU 提交与退休由独立 MPMC
|
||||
* 事件流进入,Plot 的唯一 tick consumer 归并并通过 double-buffer 发布。
|
||||
*/
|
||||
struct Frame_Policy_3D final : double_buffer::Def<
|
||||
Frame_Policy_3D, Frame_Policy,
|
||||
double_buffer::Mpmc_Triple_Buffer<
|
||||
detail::Frame_Policy_3D_Event_Stream,
|
||||
detail::Frame_Policy_3D_Event>> {
|
||||
struct Prop : Prev_Prop {};
|
||||
struct State : Prev_State {
|
||||
std::size_t pipeline_capacity{3}; /* Scene 可绑定的物理 3D 帧槽数量。 */
|
||||
std::uint64_t gpu_submission_count{}; /* Vulkan 实际提交的累计帧数。 */
|
||||
std::uint64_t overlapped_release_count{}; /* 提交后即开放下一次 Prepare 的累计帧数。 */
|
||||
std::uint64_t completion_gated_release_count{}; /* 因共享资源而等 GPU 退休后开放的累计帧数。 */
|
||||
std::uint64_t gpu_completion_count{}; /* fence 正常或失败退休的累计帧数。 */
|
||||
std::uint64_t gpu_in_flight{}; /* 已实际提交且尚未退休的当前帧数。 */
|
||||
std::uint64_t peak_gpu_in_flight{}; /* 本统计代次内 gpu_in_flight 峰值。 */
|
||||
std::uint64_t last_submitted_sequence{}; /* 最近实际提交的帧序号;未提交时为 0。 */
|
||||
std::uint64_t last_completed_sequence{}; /* 最近退休的帧序号;未退休时为 0。 */
|
||||
bool operator==(const State&) const = default;
|
||||
};
|
||||
struct Private : Prev_Private {};
|
||||
|
||||
void record_gpu_submitted(std::uint64_t sequence, bool overlaps_gpu);
|
||||
void record_gpu_completed(std::uint64_t sequence);
|
||||
void reset_3d_statistics();
|
||||
[[nodiscard]] bool consume_3d_events();
|
||||
|
||||
private:
|
||||
void submit_3d(detail::Frame_Policy_3D_Event event);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "Frame_Policy/Frame_Policy_3D.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(frame_policy_3d, publishes_gpu_pipeline_facts_without_changing_common_policy) {
|
||||
auto built = aethera::Frame_Policy_3D::Builder<
|
||||
aethera::Frame_Policy_3D>{}.build();
|
||||
ASSERT_TRUE(built.has_value());
|
||||
auto policy = std::move(*built);
|
||||
|
||||
policy->record_gpu_submitted(11, true);
|
||||
policy->record_gpu_submitted(12, false);
|
||||
policy->record_gpu_completed(11);
|
||||
ASSERT_TRUE(policy->consume_3d_events());
|
||||
|
||||
const auto& pipeline = policy->read_state<
|
||||
aethera::Frame_Policy_3D::Base_Tag>();
|
||||
EXPECT_EQ(pipeline.pipeline_capacity, 3u);
|
||||
EXPECT_EQ(pipeline.gpu_submission_count, 2u);
|
||||
EXPECT_EQ(pipeline.overlapped_release_count, 1u);
|
||||
EXPECT_EQ(pipeline.completion_gated_release_count, 1u);
|
||||
EXPECT_EQ(pipeline.gpu_completion_count, 1u);
|
||||
EXPECT_EQ(pipeline.gpu_in_flight, 1u);
|
||||
EXPECT_EQ(pipeline.peak_gpu_in_flight, 2u);
|
||||
EXPECT_EQ(pipeline.last_submitted_sequence, 12u);
|
||||
EXPECT_EQ(pipeline.last_completed_sequence, 11u);
|
||||
|
||||
const auto& common = policy->read_state<aethera::Frame_Policy::Base_Tag>();
|
||||
EXPECT_EQ(common.submitted_frame_count, 0u);
|
||||
EXPECT_EQ(common.completed_frame_count, 0u);
|
||||
EXPECT_EQ(common.mode, aethera::Frame_Pacing_Mode::fixed_rate);
|
||||
}
|
||||
|
||||
TEST(frame_policy_3d, reset_preserves_only_current_in_flight_ownership) {
|
||||
auto built = aethera::Frame_Policy_3D::Builder<
|
||||
aethera::Frame_Policy_3D>{}.build();
|
||||
ASSERT_TRUE(built.has_value());
|
||||
auto policy = std::move(*built);
|
||||
|
||||
policy->record_gpu_submitted(21, true);
|
||||
ASSERT_TRUE(policy->consume_3d_events());
|
||||
policy->reset_3d_statistics();
|
||||
ASSERT_TRUE(policy->consume_3d_events());
|
||||
|
||||
const auto& state = policy->read_state<
|
||||
aethera::Frame_Policy_3D::Base_Tag>();
|
||||
EXPECT_EQ(state.pipeline_capacity, 3u);
|
||||
EXPECT_EQ(state.gpu_submission_count, 0u);
|
||||
EXPECT_EQ(state.gpu_completion_count, 0u);
|
||||
EXPECT_EQ(state.gpu_in_flight, 1u);
|
||||
EXPECT_EQ(state.peak_gpu_in_flight, 1u);
|
||||
EXPECT_EQ(state.last_submitted_sequence, 0u);
|
||||
EXPECT_EQ(state.last_completed_sequence, 0u);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user