更新错误代码以支持WebGPU,添加窗口最小化功能,优化交换链处理

This commit is contained in:
2026-01-19 20:32:59 +08:00
parent 4357ecaa26
commit 581d90924f
7 changed files with 85 additions and 33 deletions

View File

@@ -7,6 +7,7 @@ using namespace mirai;
int main(int argc, char* argv[]) {
mirai_app_config config;
config.window_mgr_config.main_window.size = vec2i{800, 600};
config.window_mgr_config.main_window.flags = SDL_WINDOW_RESIZABLE;
mirai::mirai_app app;
app.setup(config);

View File

@@ -15,5 +15,5 @@ fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) ve
@fragment
fn fs_main() -> @location(0) vec4<f32> {
// 输出红色
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
return vec4<f32>(0.2, 0.0, 0.2, 1.0);
}

View File

@@ -13,7 +13,7 @@
namespace mirai {
void wgpu_context::test_shader() {
std::filesystem::path shader_path = R"(F:\Projects\mirai\src\render\test_shader_code.wgsl)";
std::filesystem::path shader_path = R"(D:\Projects\mirai\src\render\test_shader_code.wgsl)";
auto code = make_obj<shader_file_code>(shader_path);
auto sm = make_obj<shader_module>(wgpu_device_, code);

View File

@@ -68,8 +68,8 @@ enum class error_code : u32 {
corrupted_file = 206,
// ---- 图形/渲染错误 (300-399) ----
/// Vulkan 初始化失败
vulkan_init_failed = 300,
/// WebGPU 初始化失败
wgpu_init_failed = 300,
/// 设备不支持
device_not_supported = 301,
/// 着色器编译失败
@@ -87,7 +87,9 @@ enum class error_code : u32 {
/// 资源绑定错误
resource_binding_error = 308,
/// 分配失败
vulkan_allocation_failed = 309,
allocation_failed = 309,
/// 无效操作
invalid_operation = 310,
// ---- 窗口/输入错误 (400-499) ----
/// 窗口创建失败
@@ -183,7 +185,7 @@ enum class error_code : u32 {
return "Invalid format";
case error_code::corrupted_file:
return "Corrupted file";
case error_code::vulkan_init_failed:
case error_code::wgpu_init_failed:
return "Vulkan initialization failed";
case error_code::device_not_supported:
return "Device not supported";

View File

@@ -47,18 +47,44 @@ namespace mirai {
return;
}
}
const auto& size = get_framebuffer_size();
// size.all() 返回宽高都大于 0
if (is_minimized() || !size.all()) {
// 窗口被最小化或尺寸无效, 跳过渲染
return;
}
auto swapchain_result = acquire_next_swapchain_texture();
if (!swapchain_result.has_value()) {
switch (swapchain_result.error()) {
case wgpu::SurfaceGetCurrentTextureStatus::Outdated:
need_swapchain_rebuild_ = true;
MIRAI_LOG_WARN("交换链过时, 需要重建");
return;
case wgpu::SurfaceGetCurrentTextureStatus::Lost:
need_swapchain_rebuild_ = true;
MIRAI_LOG_WARN("交换链丢失, 需要重建");
return;
case wgpu::SurfaceGetCurrentTextureStatus::Timeout:
MIRAI_LOG_ERROR("获取交换链纹理超时");
break;
default:
MIRAI_LOG_ERROR("获取交换链纹理失败: 状态码 {}", static_cast<int>(swapchain_result.error()));
}
return;
}
auto [texture, texture_view] = swapchain_result.value();
wgpu::raii::CommandEncoder encoder = wgpu_context::instance().get_command_encoder();
wgpu::raii::Queue queue = wgpu_context::instance().get_queue();
auto size = get_framebuffer_size();
auto pipeline = wgpu_context::instance().get_test_pipeline();
auto [texture, texture_view] = acquire_next_swapchain_texture();
auto pipeline = wgpu_context::instance().get_test_pipeline();
wgpu::RenderPassColorAttachment color_attachment{};
color_attachment.setDefault();
color_attachment.view = texture_view;
color_attachment.loadOp = wgpu::LoadOp::Clear;
color_attachment.storeOp = wgpu::StoreOp::Store;
color_attachment.clearValue = {0.95f, 0.35f, 0.49f, 1.0f};
color_attachment.view = texture_view;
color_attachment.loadOp = wgpu::LoadOp::Clear;
color_attachment.storeOp = wgpu::StoreOp::Store;
color_attachment.clearValue = {0.95f, 0.35f, 0.49f, 1.0f};
wgpu::RenderPassDescriptor render_pass_descriptor{};
render_pass_descriptor.setDefault();
@@ -106,6 +132,10 @@ namespace mirai {
need_swapchain_rebuild_ = true;
}
void window::minimize_window() {
SDL_MinimizeWindow(window_);
}
vec2i window::get_pos() const {
int x, y;
if (!SDL_GetWindowPosition(window_, &x, &y)) {
@@ -120,7 +150,7 @@ namespace mirai {
int width, height;
if (!SDL_GetWindowSizeInPixels(window_, &width, &height)) {
MIRAI_LOG_ERROR("SDL_Vulkan_GetDrawableSize 失败: {}", SDL_GetError());
width = 0;
width = 0;
height = 0;
}
return vec2i{width, height};
@@ -130,12 +160,17 @@ namespace mirai {
int width, height;
if (!SDL_GetWindowSize(window_, &width, &height)) {
MIRAI_LOG_ERROR("SDL_GetWindowSize 失败: {}", SDL_GetError());
width = 0;
width = 0;
height = 0;
}
return vec2i{width, height};
}
bool window::is_minimized() const {
auto flags = SDL_GetWindowFlags(window_);
return (flags & SDL_WINDOW_MINIMIZED) != 0;
}
bool window::need_rebuild_swapchain() const {
if (!wgpu_surface_) {
return false;
@@ -144,13 +179,26 @@ namespace mirai {
}
void_result_t window::rebuild_swapchain(bool hdr_enabled, vec2i new_extent) {
if (!wgpu_surface_) {
return MAKE_ERROR_INFO(error_code::invalid_operation,
"无法重建交换链: WGPU Surface 未创建");
}
if (new_extent.x() <= 0 || new_extent.y() <= 0) {
return MAKE_ERROR_INFO(error_code::invalid_argument,
"无法重建交换链: 提供了无效的交换链尺寸 {}x{}", new_extent.x(), new_extent.y());
}
if (!need_swapchain_rebuild_) {
return {};
}
hdr_enabled_ = hdr_enabled;
wgpu::SurfaceConfiguration wgpu_surface_config{};
wgpu_surface_config.setDefault();
wgpu_surface_config.usage = wgpu::TextureUsage::RenderAttachment;
wgpu_surface_config.usage = wgpu::TextureUsage::RenderAttachment;
wgpu_surface_config.device = wgpu_context::instance().get_device();
wgpu_surface_config.format = hdr_enabled ? wgpu::TextureFormat::RGB10A2Unorm : wgpu::TextureFormat::BGRA8Unorm;
wgpu_surface_config.width = static_cast<uint32_t>(new_extent.x());
wgpu_surface_config.height = static_cast<uint32_t>(new_extent.y());
wgpu_surface_config.format = hdr_enabled ? wgpu::TextureFormat::RGB10A2Unorm : wgpu::TextureFormat::BGRA8Unorm;
wgpu_surface_config.width = static_cast<uint32_t>(new_extent.x());
wgpu_surface_config.height = static_cast<uint32_t>(new_extent.y());
wgpu_surface_config.presentMode = wgpu::PresentMode::Mailbox;
wgpu_surface_config.alphaMode = wgpu::CompositeAlphaMode::Auto;
wgpu_surface_.configure(wgpu_surface_config);
@@ -158,25 +206,24 @@ namespace mirai {
return {};
}
std::pair<wgpu::SurfaceTexture, wgpu::TextureView> window::acquire_next_swapchain_texture() {
result_t<std::pair<wgpu::SurfaceTexture, wgpu::TextureView>, wgpu::SurfaceGetCurrentTextureStatus> window::acquire_next_swapchain_texture() {
wgpu::SurfaceTexture swapchain_texture;
wgpu_surface_.getCurrentTexture(&swapchain_texture);
if (swapchain_texture.status != wgpu::SurfaceGetCurrentTextureStatus::Success) {
MIRAI_LOG_ERROR("获取交换链纹理失败,状态码: {}", static_cast<int>(swapchain_texture.status));
return {swapchain_texture, nullptr};
return std::unexpected(swapchain_texture.status);
}
wgpu::TextureViewDescriptor view_desc{};
view_desc.setDefault();
view_desc.label = "Surface Texture View";
view_desc.format = wgpuTextureGetFormat(swapchain_texture.texture);
view_desc.dimension = wgpu::TextureViewDimension::_2D;
view_desc.baseMipLevel = 0;
view_desc.mipLevelCount = 1;
view_desc.baseArrayLayer = 0;
view_desc.label = "Surface Texture View";
view_desc.format = wgpuTextureGetFormat(swapchain_texture.texture);
view_desc.dimension = wgpu::TextureViewDimension::_2D;
view_desc.baseMipLevel = 0;
view_desc.mipLevelCount = 1;
view_desc.baseArrayLayer = 0;
view_desc.arrayLayerCount = 1;
view_desc.aspect = wgpu::TextureAspect::All;
auto texture_view = wgpuTextureCreateView(swapchain_texture.texture, &view_desc);
return {swapchain_texture, texture_view};
view_desc.aspect = wgpu::TextureAspect::All;
auto texture_view = wgpuTextureCreateView(swapchain_texture.texture, &view_desc);
return std::make_pair(swapchain_texture, wgpu::TextureView{texture_view});
}
void window::on_created() {

View File

@@ -34,6 +34,7 @@ namespace mirai {
std::string get_window_title();
void resize(vec2i new_size);
void minimize_window();
vec2i get_pos() const;
vec2i get_framebuffer_size() const;
@@ -42,6 +43,7 @@ namespace mirai {
auto is_closing() const {
return closing_;
}
bool is_minimized() const;
bool need_rebuild_swapchain() const;
void_result_t rebuild_swapchain(bool hdr_enabled, vec2i new_extent);
@@ -52,7 +54,7 @@ namespace mirai {
return wgpu_surface_;
}
std::pair<wgpu::SurfaceTexture, wgpu::TextureView> acquire_next_swapchain_texture();
result_t<std::pair<wgpu::SurfaceTexture, wgpu::TextureView>, wgpu::SurfaceGetCurrentTextureStatus> acquire_next_swapchain_texture();
protected:
void on_created() override;
void on_destroying() override;

View File

@@ -55,7 +55,7 @@ namespace mirai {
if (event.type == SDL_EVENT_QUIT) {
g_quit_requested = true;
}
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
else if (event.type == SDL_EVENT_WINDOW_RESIZED) {
auto win = get_window_by_id(event.window.windowID).lock();
if (win) {
win->resize(vec2i{event.window.data1, event.window.data2});