#include "gpu_context.hpp" #include #include auto GpuContext::init(SDL_Window* window) -> bool { window_ = window; // Create GPU device: Metal on Apple, Vulkan elsewhere #ifdef __APPLE__ SDL_GPUShaderFormat preferred = SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB; #else SDL_GPUShaderFormat preferred = SDL_GPU_SHADERFORMAT_SPIRV; #endif device_ = SDL_CreateGPUDevice(preferred, false, nullptr); if (device_ == nullptr) { std::cerr << "GpuContext: SDL_CreateGPUDevice failed: " << SDL_GetError() << '\n'; return false; } std::cout << "GpuContext: driver = " << SDL_GetGPUDeviceDriver(device_) << '\n'; // Claim the window so the GPU device owns its swapchain if (!SDL_ClaimWindowForGPUDevice(device_, window_)) { std::cerr << "GpuContext: SDL_ClaimWindowForGPUDevice failed: " << SDL_GetError() << '\n'; SDL_DestroyGPUDevice(device_); device_ = nullptr; return false; } // Query swapchain format (Metal: typically B8G8R8A8_UNORM or R8G8B8A8_UNORM) swapchain_format_ = SDL_GetGPUSwapchainTextureFormat(device_, window_); std::cout << "GpuContext: swapchain format = " << static_cast(swapchain_format_) << '\n'; // Default: VSync ON SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC); return true; } void GpuContext::destroy() { if (device_ != nullptr) { SDL_WaitForGPUIdle(device_); SDL_ReleaseWindowFromGPUDevice(device_, window_); SDL_DestroyGPUDevice(device_); device_ = nullptr; } window_ = nullptr; } auto GpuContext::acquireCommandBuffer() -> SDL_GPUCommandBuffer* { SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_); if (cmd == nullptr) { SDL_Log("GpuContext: SDL_AcquireGPUCommandBuffer failed: %s", SDL_GetError()); } return cmd; } auto GpuContext::acquireSwapchainTexture(SDL_GPUCommandBuffer* cmd_buf, Uint32* out_w, Uint32* out_h) -> SDL_GPUTexture* { SDL_GPUTexture* tex = nullptr; if (!SDL_AcquireGPUSwapchainTexture(cmd_buf, window_, &tex, out_w, out_h)) { SDL_Log("GpuContext: SDL_AcquireGPUSwapchainTexture failed: %s", SDL_GetError()); return nullptr; } // tex == nullptr when window is minimized — caller should skip rendering return tex; } void GpuContext::submit(SDL_GPUCommandBuffer* cmd_buf) { SDL_SubmitGPUCommandBuffer(cmd_buf); } auto GpuContext::setVSync(bool enabled) -> bool { SDL_GPUPresentMode mode = enabled ? SDL_GPU_PRESENTMODE_VSYNC : SDL_GPU_PRESENTMODE_IMMEDIATE; return SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, mode); }