/* Copyright (c) 2019-2025, Arm Limited and Contributors * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 the "License"; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include "apps.h" #include "common/optional.h" #include "common/utils.h" #include "common/vk_common.h" #include "platform/application.h" #include "platform/plugins/plugin.h" #include "platform/window.h" #include "rendering/render_context.h" #if defined(VK_USE_PLATFORM_XLIB_KHR) # undef Success #endif namespace vkb { enum class ExitCode { Success = 0, /* App executed as expected */ NoSample, /* App should show help how to run a sample */ Help, /* App should show help */ Close, /* App has been requested to close at initialization */ FatalError /* App encountered an unexpected error */ }; class Platform { public: Platform(const PlatformContext &context); virtual ~Platform() = default; /** * @brief Initialize the platform * @param plugins plugins available to the platform * @return An exit code representing the outcome of initialization */ virtual ExitCode initialize(const std::vector &plugins); /** * @brief Handles the main update and render loop * @return An exit code representing the outcome of the loop */ ExitCode main_loop(); /** * @brief Handles the update and render of a frame. * Called either from main_loop(), or from a platform-specific * frame-looping mechanism, typically tied to platform screen refeshes. * @return An exit code representing the outcome of the loop */ ExitCode main_loop_frame(); /** * @brief Runs the application for one frame */ void update(); /** * @brief Terminates the platform and the application * @param code Determines how the platform should exit */ virtual void terminate(ExitCode code); /** * @brief Requests to close the platform at the next available point */ virtual void close(); std::string &get_last_error(); virtual void resize(uint32_t width, uint32_t height); virtual void input_event(const InputEvent &input_event); Window &get_window(); Application &get_app() const; Application &get_app(); void set_last_error(const std::string &error); template T *get_plugin() const; template bool using_plugin() const; void set_focus(bool focused); void request_application(const apps::AppInfo *app); bool app_requested(); bool start_app(); void force_simulation_fps(float fps); // Force the application to always render even if it is not in focus void force_render(bool should_always_render); void disable_input_processing(); void set_window_properties(const Window::OptionalProperties &properties); void on_post_draw(RenderContext &context); static const uint32_t MIN_WINDOW_WIDTH; static const uint32_t MIN_WINDOW_HEIGHT; protected: std::vector active_plugins; std::unordered_map> hooks; std::unique_ptr window{nullptr}; std::unique_ptr active_app{nullptr}; virtual std::vector get_platform_sinks(); /** * @brief Handles the creation of the window * * @param properties Preferred window configuration */ virtual void create_window(const Window::Properties &properties) = 0; void register_hooks(Plugin *plugin); void on_update(float delta_time); void on_app_error(const std::string &app_id); void on_app_start(const std::string &app_id); void on_app_close(const std::string &app_id); void on_platform_close(); void on_update_ui_overlay(vkb::Drawer &drawer); Window::Properties window_properties; /* Source of truth for window state */ bool fixed_simulation_fps{false}; /* Delta time should be fixed with a fabricated value */ bool always_render{false}; /* App should always render even if not in focus */ float simulation_frame_time = 0.016f; /* A fabricated delta time */ bool process_input_events{true}; /* App should continue processing input events */ bool focused{true}; /* App is currently in focus at an operating system level */ bool close_requested{false}; /* Close requested */ protected: std::vector plugins; private: Timer timer; const apps::AppInfo *requested_app{nullptr}; std::vector arguments; std::string last_error; std::map command_map; std::map option_map; }; template bool Platform::using_plugin() const { return !plugins::with_tags(active_plugins).empty(); } template T *Platform::get_plugin() const { assert(using_plugin() && "Plugin is not enabled but was requested"); const auto plugins = plugins::with_tags(active_plugins); return dynamic_cast(plugins[0]); } } // namespace vkb