#include #include #include #include #include #include #include "renderer.h" constexpr int WINDOW_WIDTH = 1280; constexpr int WINDOW_HEIGHT = 720; class Application { public: Application() : window_(nullptr) {} ~Application() { cleanup(); } bool initialize() { if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return false; } glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); window_ = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "TimePlot - C++ WebGPU", nullptr, nullptr); if (!window_) { std::cerr << "Failed to create window" << std::endl; return false; } glfwSetWindowUserPointer(window_, this); glfwSetKeyCallback(window_, keyCallback); glfwSetFramebufferSizeCallback(window_, resizeCallback); if (!initWebGPU()) { return false; } renderer_ = std::make_unique(device_, surface_, WINDOW_WIDTH, WINDOW_HEIGHT); if (!renderer_->initialize()) { std::cerr << "Failed to initialize renderer" << std::endl; return false; } return true; } void run() { while (!glfwWindowShouldClose(window_)) { glfwPollEvents(); renderer_->update(); renderer_->render(); } } private: bool initWebGPU() { // Create instance instance_ = wgpu::createInstance(wgpu::InstanceDescriptor{}); if (!instance_) { std::cerr << "Failed to create WebGPU instance" << std::endl; return false; } // Create surface from GLFW window surface_ = glfwCreateWindowWGPUSurface(instance_, window_); if (!surface_) { std::cerr << "Failed to create surface" << std::endl; return false; } // Request adapter (synchronous version) wgpu::RequestAdapterOptions adapterOpts{}; adapterOpts.compatibleSurface = surface_; wgpu::Adapter adapter = instance_.requestAdapter(adapterOpts); if (!adapter) { std::cerr << "Failed to get adapter" << std::endl; return false; } // Request device (synchronous version) wgpu::DeviceDescriptor deviceDesc{}; device_ = adapter.requestDevice(deviceDesc); if (!device_) { std::cerr << "Failed to get device" << std::endl; return false; } return true; } void cleanup() { renderer_.reset(); if (window_) { glfwDestroyWindow(window_); window_ = nullptr; } glfwTerminate(); } static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { auto* app = static_cast(glfwGetWindowUserPointer(window)); if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE) { glfwSetWindowShouldClose(window, GLFW_TRUE); } else if (key == GLFW_KEY_G) { app->renderer_->toggleGrid(); } } } static void resizeCallback(GLFWwindow* window, int width, int height) { auto* app = static_cast(glfwGetWindowUserPointer(window)); app->renderer_->resize(width, height); } GLFWwindow* window_; wgpu::Instance instance_; wgpu::Device device_; wgpu::Surface surface_; std::unique_ptr renderer_; }; int main() { Application app; if (!app.initialize()) { return EXIT_FAILURE; } app.run(); return EXIT_SUCCESS; }