异步线程绘制

This commit is contained in:
Nanako 2025-02-23 23:45:11 +08:00
parent 09304715ed
commit 192bb51f1d
14 changed files with 210 additions and 85 deletions

View File

@ -6,5 +6,6 @@ int main(int argc, char* argv[]) {
init.size = {800, 600};
init.resizable = true;
init.centered = true;
// init.api = mirage::renderer_api::opengl;
return run(init);
}

View File

@ -245,13 +245,17 @@ def generate_pipeline_header_preamble() -> List[str]:
" throw std::runtime_error(\"Failed to read shader file: \" + std::string(e.what()));",
" }",
"",
" bool is_string_source = rendererID == LLGL::RendererID::OpenGL;",
" if (is_string_source) {",
" shaderData.push_back('\\0');",
" }",
" // 创建着色器",
" LLGL::ShaderDescriptor desc = shaderDesc;",
" desc.source = shaderData.data();",
" desc.sourceSize = shaderData.size();",
" desc.entryPoint = entryPoint;",
" desc.type = type;",
" desc.sourceType = rendererID == LLGL::RendererID::OpenGL ? LLGL::ShaderSourceType::CodeString : LLGL::ShaderSourceType::BinaryBuffer;",
" desc.sourceType = is_string_source ? LLGL::ShaderSourceType::CodeString : LLGL::ShaderSourceType::BinaryBuffer;",
"",
" auto shader = renderer->CreateShader(desc);",
" if (auto report = shader->GetReport()) {",

View File

@ -1,14 +1,16 @@
#include "mirage.h"
#include "async/thread_pool.h"
#include "misc/lazy_singleton.h"
#include "renderer/dpi_sensibility.h"
#include "window/window_manager.h"
mirage::duration_type delta_time = {};
mirage::time_type begin_time = {};
mirage::time_type last_time = {};
LLGL::RenderSystemPtr renderer = nullptr;
uint64_t frame_index = 0;
std::filesystem::path shader_path = "resource/shaders";
mirage::duration_type delta_time = {};
mirage::time_type begin_time = {};
mirage::time_type last_time = {};
LLGL::RenderSystemPtr renderer = nullptr;
uint64_t frame_index = 0;
std::filesystem::path shader_path = "resource/shaders";
namespace mirage {
void on_llgl_log(LLGL::Log::ReportType type, const char* text, void* user_data) {
@ -21,6 +23,7 @@ namespace mirage {
break;
}
}
std::string to_string(renderer_api api) {
switch (api) {
case renderer_api::dx11:
@ -36,7 +39,9 @@ namespace mirage {
}
return "Unknown";
}
bool init_renderer(const init_info& in_info) {
dpi_sensibility::init_dpi_sensibility();
RegisterCallback(on_llgl_log);
LLGL::RenderSystemDescriptor desc{};
desc.moduleName = to_string(in_info.api);
@ -57,23 +62,17 @@ namespace mirage {
return true;
}
bool init_window(const init_info& in_info) {
auto main_window = lazy_singleton<window_manager>::get().create_window(in_info);
auto window_ptr = main_window.lock();
if (!window_ptr) {
if (!lazy_singleton<window_manager>::get().init(in_info)) {
spdlog::error("窗口管理器初始化失败");
return false;
}
if (!window_ptr->create_context(in_info)) {
return false;
}
spdlog::info("主窗口创建成功");
spdlog::info("窗口管理器创建成功");
return true;
}
void destroy_renderer() {
LLGL::RenderSystem::Unload(std::move(renderer));
}
bool init(const init_info& in_info) {
spdlog::info("初始化 mirage");
if (!init_renderer(in_info)) {
@ -104,6 +103,7 @@ namespace mirage {
last_time = current_time;
lazy_singleton<window_manager>::get().update(delta_time);
frame_index++;
std::this_thread::yield();
}
@ -130,7 +130,6 @@ namespace mirage {
}
while (!should_exit()) {
update();
frame_index++;
}
destroy();
} catch (const std::exception& e) {

View File

@ -95,7 +95,7 @@ namespace mirage {
};
struct triangle_index_t {
int32_t vertex_index[3];
uint32_t vertex_index[3];
};
struct pipeline_info {

View File

@ -0,0 +1,30 @@
#pragma once
#if MIRAGE_PLATFORM_WINDOWS
#include <Windows.h>
#include <ShellScalingApi.h>
#pragma comment(lib, "Shcore.lib")
#endif
#include <spdlog/spdlog.h>
namespace mirage {
class dpi_sensibility {
public:
static void init_dpi_sensibility() {
dpi_sensibility_impl();
}
private:
#if MIRAGE_PLATFORM_WINDOWS
static void dpi_sensibility_impl() {
if (SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)) {
spdlog::info("设置DPI感知上下文成功");
}
}
#else
static void dpi_sensibility_impl() {
spdlog::warn("当前平台不支持DPI感知");
}
#endif
};
}

View File

@ -15,15 +15,20 @@ namespace mirage {
if (command_buffer) {
get_renderer()->Release(*command_buffer);
}
if (swap_chain) {
get_renderer()->Release(*swap_chain);
}
}
bool render_context::init(const swap_chain_descriptor& in_desc, const std::shared_ptr<LLGL::Surface>& in_surface) {
LLGL::SwapChainDescriptor temp = in_desc;
temp.resolution = in_surface->GetContentSize();
swap_chain = get_renderer()->CreateSwapChain(temp, in_surface);
temp.resolution = in_surface->GetContentSize();
swap_chain = get_renderer()->CreateSwapChain(temp, in_surface);
if (swap_chain == nullptr) {
spdlog::error("无法创建交换链");
return false;
}
command_buffer = get_renderer()->CreateCommandBuffer(LLGL::CommandBufferFlags::ImmediateSubmit);
if (command_buffer == nullptr) {
spdlog::error("无法创建命令缓冲区");
@ -47,32 +52,10 @@ namespace mirage {
);
pipeline = generated_pipelines::create_aorii_rect_pipeline(get_renderer(), swap_chain->GetRenderPass(), pipeline_layout_desc);
vertex va{};
va.position = {0.0f, 0.0f};
va.uv = {0.0f, 0.0f};
va.color = {1.0f, 1.0f, 0.0f, 1.0f};
vertex vb{};
vb.position = {100.0f, 0.0f};
vb.uv = {1.0f, 0.0f};
vb.color = {1.0f, 0.0f, 1.0f, 1.0f};
vertex vc{};
vc.position = {100.0f, 100.0f};
vc.uv = {1.0f, 1.0f};
vc.color = {0.0f, 1.0f, 1.0f, 1.0f};
vertex vd{};
vd.position = {0.0f, 100.0f};
vd.uv = {0.0f, 1.0f};
vd.color = {0.0f, 1.0f, 0.0f, 1.0f};
std::vector quad_vertices = {va, vb, vc, vd};
vertex_buffer->push(quad_vertices);
triangle_index_t ta{0, 1, 2};
triangle_index_t tb{0, 2, 3};
std::vector quad_indices = {ta, tb};
index_buffer->push(quad_indices);
push_rectangle({0, 0}, {100, 100}, linear_color::white);
return true;
}
render_context::update_status render_context::update(const duration_type& in_delta_time) {
if (!command_buffer || !swap_chain) {
return update_status::fail;
@ -80,15 +63,22 @@ namespace mirage {
if (!swap_chain->IsPresentable()) {
return update_status::wait_for_present;
}
command_buffer->Begin();
{
if (auto size = new_size.exchange({})) {
swap_chain->ResizeBuffers(size.value());
pipeline_param param;
param.mvp = get_projection_matrix();
param_buffer->set(param);
}
command_buffer->Begin(); {
command_buffer->SetViewport(swap_chain->GetResolution());
command_buffer->SetVertexBuffer(vertex_buffer->get_raw());
command_buffer->SetIndexBuffer(index_buffer->get_raw());
command_buffer->BeginRenderPass(*swap_chain);
{
command_buffer->BeginRenderPass(*swap_chain); {
command_buffer->Clear(LLGL::ClearFlags::Color, {0.1f, 0.1f, 0.2f, 1.0f});
command_buffer->Clear(LLGL::ClearFlags::Depth);
command_buffer->SetPipelineState(*pipeline.pipeline_state);
command_buffer->SetResource(0, param_buffer->get_raw());
@ -98,49 +88,87 @@ namespace mirage {
command_buffer->EndRenderPass();
}
command_buffer->End();
get_renderer()->GetCommandQueue()->Submit(*command_buffer);
swap_chain->Present();
return update_status::success;
}
void render_context::resize_swap_chain(const LLGL::Extent2D& in_size, long in_flag) {
if (swap_chain) {
swap_chain->ResizeBuffers(in_size, in_flag);
pipeline_param param;
param.mvp = get_projection_matrix();
param_buffer->set(param);
}
void render_context::resize_swap_chain(const LLGL::Extent2D& in_size, long in_flag) {
if (!swap_chain)
return;
new_size = in_size;
}
void render_context::set_vsync(bool in_vsync) {
if (swap_chain) {
swap_chain->SetVsyncInterval(in_vsync ? 1 : 0);
vsync = in_vsync;
spdlog::info("垂直同步: {}", vsync);
}
if (!swap_chain)
return;
swap_chain->SetVsyncInterval(in_vsync ? 1 : 0);
vsync = in_vsync;
spdlog::info("垂直同步: {}", vsync);
}
void render_context::push_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color_type& in_color) {
vertex va{};
vertex vb{};
vertex vc{};
vertex vd{};
va.color = in_color;
vb.color = in_color;
vc.color = in_color;
vd.color = in_color;
va.position = in_pos;
vb.position = {in_pos.x() + in_size.x(), in_pos.y()};
vc.position = in_pos + in_size;
vd.position = {in_pos.x(), in_pos.y() + in_size.y()};
va.uv = {0.0f, 0.0f};
vb.uv = {1.0f, 0.0f};
vc.uv = {1.0f, 1.0f};
vd.uv = {0.0f, 1.0f};
const auto index_offset = static_cast<uint32_t>(vertex_buffer->get_size() / sizeof(vertex));
// 根据index_offset计算索引
const triangle_index_t ta = {0 + index_offset, 1 + index_offset, 2 + index_offset};
const triangle_index_t tb = {0 + index_offset, 2 + index_offset, 3 + index_offset};
std::vector quad_indices = {ta, tb};
std::vector quad_vertices = {va, vb, vc, vd};
vertex_buffer->push(quad_vertices);
index_buffer->push(quad_indices);
}
Eigen::Matrix4f render_context::get_projection_matrix() const {
const bool is_clip_range_unit_cube = get_renderer()->GetRenderingCaps().clippingRange == LLGL::ClippingRange::MinusOneToOne;
const auto& size = swap_chain->GetResolution();
// 创建一个单位矩阵
Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
// 透视投影矩阵
if (is_clip_range_unit_cube) {
matrix(0, 0) = 2.0f / size.width;
matrix(1, 1) = 2.0f / size.height;
matrix(2, 2) = 1.0f;
matrix(3, 3) = 1.0f;
matrix(3, 0) = -1.0f;
matrix(3, 1) = -1.0f;
} else {
// 对于 [-1, 1] 的裁剪范围
matrix(0, 0) = 2.0f / size.width;
matrix(1, 1) = -2.0f / size.height;
matrix(2, 2) = 1.0f;
matrix(3, 3) = 1.0f;
matrix(3, 0) = -1.0f;
matrix(3, 1) = 1.0f;
// 调整Z轴范围从[-1,1]
matrix(2, 2) = 2.0f;
matrix(3, 2) = -1.0f;
} else {
// 对于 [0, 1] 的裁剪范围
matrix(0, 0) = 2.0f / size.width;
matrix(1, 1) = -2.0f / size.height;
matrix(2, 2) = 1.0f;
matrix(3, 3) = 1.0f;
matrix(3, 0) = -1.0f;
matrix(3, 1) = 1.0f;
// 调整Z轴范围从[0,1]
matrix(2, 2) = 1.0f;
matrix(3, 2) = 0.0f;
}
return matrix;
}
} // namespace mirage

View File

@ -29,6 +29,12 @@ namespace mirage {
}
[[nodiscard]] Eigen::Matrix4f get_projection_matrix() const;
void push_rectangle(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size, const linear_color_type& in_color);
void reset_vertices() {
vertex_buffer->clear();
index_buffer->clear();
}
private:
std::shared_ptr<render_buffer> vertex_buffer;
std::shared_ptr<render_buffer> index_buffer;
@ -37,5 +43,6 @@ namespace mirage {
LLGL::SwapChain* swap_chain = nullptr;
bool vsync = true;
pipeline_info pipeline;
std::atomic<std::optional<LLGL::Extent2D>> new_size;
};
} // namespace mirage

View File

@ -1,5 +1,6 @@
#pragma once
#include "LLGL/LLGL.h"
#include "misc/color.h"
#include "misc/enum_class_flags.h"
#include <Eigen/Eigen>
#include <cstdint>
@ -7,7 +8,7 @@
namespace mirage {
using transform_type = Eigen::Affine2d;
using color_type = LLGL::ColorRGBAub;
using linear_color_type = LLGL::ColorRGBAf;
using linear_color_type = linear_color;
using point_type = Eigen::Vector2f;
struct vertex_shader_param {

View File

@ -15,7 +15,7 @@ struct PSInput {
PSInput vertex_main(VSInput input)
{
PSInput output;
output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform);
output.position = mul(float4(input.position, 0, 1.0), param_buffer.transform);
output.color = input.color;
return output;
}

View File

@ -1,3 +1,4 @@
#include "misc/lazy_singleton.h"
#include "window/window.h"
#include "window/window_manager.h"
#include <spdlog/spdlog.h>
@ -164,6 +165,12 @@ namespace mirage {
return {};
}
void window::on_resize(const LLGL::Extent2D& in_client_area_size) {
if (context) {
context->resize_swap_chain(in_client_area_size, 0);
}
}
void window::init_event_listener() {
if (auto window_ptr = static_cast<LLGL::Window*>(surface.get())) {
window_ptr->SetUserData(this);

View File

@ -43,7 +43,7 @@ namespace mirage {
}
#endif
void window::update(const duration_type& in_delta_time) {
void window::render_update(const duration_type& in_delta_time) {
if (context) {
context->update(in_delta_time);
}

View File

@ -17,7 +17,7 @@ namespace mirage {
}
[[nodiscard]] void* get_native_handle() const;
void update(const duration_type& in_delta_time);
void render_update(const duration_type& in_delta_time);
void set_title(const std::u8string& in_title);
[[nodiscard]] std::u8string get_title() const;
void set_fullscreen(bool in_fullscreen);
@ -43,7 +43,7 @@ namespace mirage {
virtual void on_wheel_motion(int in_motion) {}
virtual void on_local_motion(const LLGL::Offset2D& in_position) {}
virtual void on_global_motion(const LLGL::Offset2D& in_motion) {}
virtual void on_resize(const LLGL::Extent2D& in_client_area_size) {}
virtual void on_resize(const LLGL::Extent2D& in_client_area_size);
virtual void on_update() {}
virtual void on_get_focus() {}
virtual void on_lost_focus() {}

View File

@ -1,32 +1,56 @@
#include "window_manager.h"
#include <spdlog/spdlog.h>
#include <Windows.h>
namespace mirage {
void window_manager::update(const duration_type& in_delta_time) {
if (!LLGL::Surface::ProcessEvents()) {
return;
}
LLGL::Surface::ProcessEvents();
to_destroy.clear();
for (const auto& w : windows) {
w->update(in_delta_time);
}
std::shared_lock lock(mutex);
should_exit_flag = windows.empty() && to_destroy.empty();
}
bool window_manager::init(const init_info& in_info) {
auto main_window = create_window(in_info);
auto window_ptr = main_window.lock();
if (!window_ptr) {
return false;
}
if (!window_ptr->create_context(in_info)) {
return false;
}
last_time = std::chrono::high_resolution_clock::now();
render_thread = std::thread(&window_manager::render_thread_func, this);
return true;
}
bool window_manager::destroy() {
should_exit_flag = true;
render_thread.join();
windows.clear();
to_destroy.clear();
return true;
}
std::weak_ptr<window> window_manager::create_window(const LLGL::WindowDescriptor& desc) {
auto window_ptr = std::make_shared<window>(desc);
windows.push_back(window_ptr);
{
std::unique_lock lock(mutex);
windows.push_back(window_ptr);
}
if (!window_ptr) {
spdlog::error("无法创建窗口");
return {};
}
return window_ptr;
}
void window_manager::destroy_window(const window& in_window) {
std::unique_lock lock(mutex);
for (auto it = windows.begin(); it != windows.end(); ++it) {
if (it->get() == &in_window) {
to_destroy.push_back(*it);
@ -35,10 +59,27 @@ namespace mirage {
}
}
}
std::weak_ptr<window> window_manager::get_main_window() {
std::shared_lock lock(mutex);
if (windows.empty()) {
return {};
}
return windows.front();
}
void window_manager::render_thread_func() {
while (!should_exit_flag) {
const auto& current_time = std::chrono::high_resolution_clock::now();
const auto in_delta_time = current_time - last_time;
last_time = current_time;
std::shared_lock lock(mutex);
for (const auto& w : windows) {
w->render_update(in_delta_time);
}
std::this_thread::sleep_for(std::chrono::milliseconds(16));
}
}
} // namespace mirage

View File

@ -1,17 +1,19 @@
#pragma once
#include "misc/lazy_singleton.h"
#include <vector>
#include <memory>
#include "window.h"
#include <shared_mutex>
namespace mirage {
class window_manager {
public:
void update(const duration_type& in_delta_time);
bool init(const init_info& in_info);
bool destroy();
[[nodiscard]] bool should_exit() const {
return windows.empty() && to_destroy.empty();
return should_exit_flag;
}
std::weak_ptr<window> create_window(const LLGL::WindowDescriptor& desc);
@ -24,9 +26,14 @@ namespace mirage {
}
return result;
}
private:
std::vector<std::shared_ptr<window>> windows;
std::vector<std::shared_ptr<window>> to_destroy;
void render_thread_func();
std::thread render_thread;
time_type last_time = {};
std::atomic_bool should_exit_flag = false;
std::shared_mutex mutex;
};
} // namespace mirage