#include "window.h" #include #include "render/sdl3webgpu.h" #include #include "core/logger.h" #include "render/wgpu_context.h" namespace mirai { void_result_t window::make_window(window_config config) { auto win_ptr = SDL_CreateWindow(config.title.c_str(), config.size.x(), config.size.y(), config.flags); if (!win_ptr) { return MAKE_ERROR_INFO(error_code::window_creation_failed, "SDL_CreateWindow 失败: {}", SDL_GetError()); } if (config.wgpu_window) { wgpu_surface_ = SDL_GetWGPUSurface(wgpu_context::instance().get_instance(), win_ptr); if (!wgpu_surface_) { SDL_DestroyWindow(win_ptr); return MAKE_ERROR_INFO(error_code::window_creation_failed, "SDL_GetWGPUSurface 失败: {}", SDL_GetError()); } } if (!SDL_SetWindowTitle(win_ptr, config.title.c_str())) { SDL_DestroyWindow(win_ptr); return MAKE_ERROR_INFO(error_code::window_creation_failed, "SDL_SetWindowTitle 失败: {}", SDL_GetError()); } window_ = win_ptr; return {}; } void window::update(duration_ms delta_time) { if (closing_) { return; } if (need_rebuild_swapchain()) { auto result = rebuild_swapchain(); if (!result) { MIRAI_LOG_ERROR("窗口 {} 交换链重建失败: {}", get_window_title(), result.error().full_description()); return; } } 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(); 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}; wgpu::RenderPassDescriptor render_pass_descriptor{}; render_pass_descriptor.setDefault(); render_pass_descriptor.colorAttachmentCount = 1; render_pass_descriptor.colorAttachments = &color_attachment; wgpu::raii::RenderPassEncoder render_pass = encoder->beginRenderPass(render_pass_descriptor); render_pass->setPipeline(pipeline); render_pass->draw(3, 1, 0, 0); render_pass->end(); wgpu::raii::CommandBuffer command_buffer = encoder->finish(); queue->submit(*command_buffer); wgpu_surface_.present(); wgpuTextureViewRelease(texture_view); wgpuTextureRelease(texture.texture); } void window::show_window(bool show) { if (show) { SDL_ShowWindow(window_); } else { SDL_HideWindow(window_); } } void window::move_window(vec2i pos) { SDL_SetWindowPosition(window_, pos.x(), pos.y()); } std::string window::get_window_title() { const char* title = SDL_GetWindowTitle(window_); if (!title) { MIRAI_LOG_ERROR("SDL_GetWindowTitle 失败: {}", SDL_GetError()); return ""; } return std::string(title); } void window::resize(vec2i new_size) { SDL_SetWindowSize(window_, new_size.x(), new_size.y()); need_swapchain_rebuild_ = true; } vec2i window::get_pos() const { int x, y; if (!SDL_GetWindowPosition(window_, &x, &y)) { MIRAI_LOG_ERROR("SDL_GetWindowPosition 失败: {}", SDL_GetError()); x = 0; y = 0; } return vec2i{x, y}; } vec2i window::get_framebuffer_size() const { int width, height; if (!SDL_GetWindowSizeInPixels(window_, &width, &height)) { MIRAI_LOG_ERROR("SDL_Vulkan_GetDrawableSize 失败: {}", SDL_GetError()); width = 0; height = 0; } return vec2i{width, height}; } vec2i window::get_window_size() const { int width, height; if (!SDL_GetWindowSize(window_, &width, &height)) { MIRAI_LOG_ERROR("SDL_GetWindowSize 失败: {}", SDL_GetError()); width = 0; height = 0; } return vec2i{width, height}; } bool window::need_rebuild_swapchain() const { if (!wgpu_surface_) { return false; } return need_swapchain_rebuild_; } void_result_t window::rebuild_swapchain(bool hdr_enabled, vec2i new_extent) { wgpu::SurfaceConfiguration wgpu_surface_config{}; wgpu_surface_config.setDefault(); 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(new_extent.x()); wgpu_surface_config.height = static_cast(new_extent.y()); wgpu_surface_config.presentMode = wgpu::PresentMode::Mailbox; wgpu_surface_config.alphaMode = wgpu::CompositeAlphaMode::Auto; wgpu_surface_.configure(wgpu_surface_config); need_swapchain_rebuild_ = false; return {}; } std::pair 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(swapchain_texture.status)); return {swapchain_texture, nullptr}; } 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.arrayLayerCount = 1; view_desc.aspect = wgpu::TextureAspect::All; auto texture_view = wgpuTextureCreateView(swapchain_texture.texture, &view_desc); return {swapchain_texture, texture_view}; } void window::on_created() { object::on_created(); } void window::on_destroying() { object::on_destroying(); if (wgpu_surface_) { wgpu_surface_.unconfigure(); wgpuSurfaceRelease(wgpu_surface_); wgpu_surface_ = nullptr; } MIRAI_LOG_INFO("窗口 {} 销毁", get_window_title()); SDL_DestroyWindow(window_); window_ = nullptr; } }