diff --git a/example/src/main.cpp b/example/src/main.cpp index 519703d..49ce53e 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -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); } diff --git a/scripts/compile_shaders.py b/scripts/compile_shaders.py index fb14fef..0796272 100644 --- a/scripts/compile_shaders.py +++ b/scripts/compile_shaders.py @@ -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()) {", diff --git a/src/core/mirage.cpp b/src/core/mirage.cpp index dff1a94..9c32710 100644 --- a/src/core/mirage.cpp +++ b/src/core/mirage.cpp @@ -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::get().create_window(in_info); - auto window_ptr = main_window.lock(); - if (!window_ptr) { + if (!lazy_singleton::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::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) { diff --git a/src/core/misc/mirage_type.h b/src/core/misc/mirage_type.h index edca52f..558b48e 100644 --- a/src/core/misc/mirage_type.h +++ b/src/core/misc/mirage_type.h @@ -95,7 +95,7 @@ namespace mirage { }; struct triangle_index_t { - int32_t vertex_index[3]; + uint32_t vertex_index[3]; }; struct pipeline_info { diff --git a/src/core/renderer/dpi_sensibility.h b/src/core/renderer/dpi_sensibility.h new file mode 100644 index 0000000..cef29c7 --- /dev/null +++ b/src/core/renderer/dpi_sensibility.h @@ -0,0 +1,30 @@ +#pragma once +#if MIRAGE_PLATFORM_WINDOWS +#include +#include +#pragma comment(lib, "Shcore.lib") +#endif + +#include + +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 + }; +} diff --git a/src/core/renderer/render_context.cpp b/src/core/renderer/render_context.cpp index dbc468c..b3cbdac 100644 --- a/src/core/renderer/render_context.cpp +++ b/src/core/renderer/render_context.cpp @@ -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& 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(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 diff --git a/src/core/renderer/render_context.h b/src/core/renderer/render_context.h index c21d51a..5486fe8 100644 --- a/src/core/renderer/render_context.h +++ b/src/core/renderer/render_context.h @@ -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 vertex_buffer; std::shared_ptr index_buffer; @@ -37,5 +43,6 @@ namespace mirage { LLGL::SwapChain* swap_chain = nullptr; bool vsync = true; pipeline_info pipeline; + std::atomic> new_size; }; } // namespace mirage diff --git a/src/core/renderer/rendering_common.h b/src/core/renderer/rendering_common.h index 97c3517..911937b 100644 --- a/src/core/renderer/rendering_common.h +++ b/src/core/renderer/rendering_common.h @@ -1,5 +1,6 @@ #pragma once #include "LLGL/LLGL.h" +#include "misc/color.h" #include "misc/enum_class_flags.h" #include #include @@ -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 { diff --git a/src/core/shaders/aorii_rect.slang b/src/core/shaders/aorii_rect.slang index 67780f6..7b47291 100644 --- a/src/core/shaders/aorii_rect.slang +++ b/src/core/shaders/aorii_rect.slang @@ -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; } diff --git a/src/core/window/desktop/desktop_window.cpp b/src/core/window/desktop/desktop_window.cpp index bc48f13..45fd179 100644 --- a/src/core/window/desktop/desktop_window.cpp +++ b/src/core/window/desktop/desktop_window.cpp @@ -1,3 +1,4 @@ +#include "misc/lazy_singleton.h" #include "window/window.h" #include "window/window_manager.h" #include @@ -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(surface.get())) { window_ptr->SetUserData(this); diff --git a/src/core/window/window.cpp b/src/core/window/window.cpp index 448f04b..a4ca143 100644 --- a/src/core/window/window.cpp +++ b/src/core/window/window.cpp @@ -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); } diff --git a/src/core/window/window.h b/src/core/window/window.h index c6587dd..bce954f 100644 --- a/src/core/window/window.h +++ b/src/core/window/window.h @@ -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() {} diff --git a/src/core/window/window_manager.cpp b/src/core/window/window_manager.cpp index 327a90b..8a7f68e 100644 --- a/src/core/window/window_manager.cpp +++ b/src/core/window/window_manager.cpp @@ -1,32 +1,56 @@ #include "window_manager.h" #include +#include 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_manager::create_window(const LLGL::WindowDescriptor& desc) { auto window_ptr = std::make_shared(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_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 diff --git a/src/core/window/window_manager.h b/src/core/window/window_manager.h index e32b8bc..a22f369 100644 --- a/src/core/window/window_manager.h +++ b/src/core/window/window_manager.h @@ -1,17 +1,19 @@ #pragma once -#include "misc/lazy_singleton.h" #include #include #include "window.h" +#include 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 create_window(const LLGL::WindowDescriptor& desc); @@ -24,9 +26,14 @@ namespace mirage { } return result; } - private: std::vector> windows; std::vector> 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