MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "mxvk_context.hpp"
5#include "mxvk_sprite.hpp"
6#include "mxvk_sprite3d.hpp"
7#include "mxvk_text.hpp"
8#include <SDL3/SDL.h>
9#include <array>
10#include <chrono>
11#include <condition_variable>
12#include <cstdint>
13#include <deque>
14#include <limits>
15#include <memory>
16#include <mutex>
17#include <mxvk/mxvk_version.hpp>
18#include <optional>
19#include <string>
20#include <thread>
21#include <vector>
22#include <volk/volk.h>
23
24#ifdef ENABLE_VALIDATION
25#define MXVK_VALIDATION true
26#else
27#define MXVK_VALIDATION false
28#endif
29
30namespace mxvk {
31 /**
32 * @brief Main Vulkan window wrapper for MXVK.
33 *
34 * The class owns SDL window resources and a minimal Vulkan bootstrap
35 * (instance + presentation surface).
36 */
37 class VK_Window {
38 public:
43
44 /**
45 * @brief Construct an empty window object.
46 */
47 VK_Window() = default;
48
49 /**
50 * @brief Destroy owned Vulkan and SDL resources.
51 */
52 virtual ~VK_Window();
53
54 /**
55 * @brief Release Vulkan and SDL resources.
56 *
57 * Safe to call multiple times.
58 */
59 void release();
60
61 /**
62 * @brief Construct and initialize a window and Vulkan context.
63 * @param title Window title string.
64 * @param width Window width in pixels.
65 * @param height Window height in pixels.
66 * @param full Enables fullscreen mode when true.
67 * @param validiation Enables validation-related behavior when true.
68 * @param presentModePreference Preferred swapchain present-mode policy.
69 */
70 VK_Window(const std::string &title, int width, int height, bool full = false, bool validiation = true, PresentModePreference presentModePreference = PresentModePreference::LowLatency);
71 VK_Window(const std::string &title, int width, int height, bool full, bool validiation, bool enableVsync);
72
73 // no copy
74 VK_Window(const VK_Window &) = delete;
75 VK_Window(VK_Window &&) = delete;
76 VK_Window &operator=(const VK_Window &) = delete;
78
79 /**
80 * @brief Initialize Vulkan state.
81 * @param validiation Enables validation-related behavior when true.
82 * @return true on success, false otherwise.
83 */
84
85 virtual bool initVulkan(bool validiation);
86
87 /**
88 * @brief Handle one SDL event.
89 * @param e SDL event to process.
90 */
91 virtual void event(SDL_Event &e);
92
93 /**
94 * @brief Run the main event/render loop.
95 */
96 void loop();
97
98 /**
99 * @brief Render one frame.
100 */
101 virtual void render();
102
103 /**
104 * @brief Save the most recently rendered window contents as a PNG file.
105 * @param path Destination PNG path.
106 *
107 * This performs a synchronous GPU readback and may briefly stall rendering.
108 */
109 void saveSnapshot(const std::string &path);
110
111 /**
112 * @brief Record resource transitions that must happen before dynamic rendering begins.
113 *
114 * This callback is invoked after the command buffer begins recording and before
115 * vkCmdBeginRendering. Override this for resources that need per-frame image
116 * transitions or uploads before they are sampled by custom rendering.
117 *
118 * @param cmd Active command buffer in recording state, outside a rendering scope.
119 * @param image_index Current swapchain image index.
120 */
121 virtual void onPrepareFrameRendering(VkCommandBuffer cmd, uint32_t image_index);
122
123 /**
124 * @brief Execute one processing/update step.
125 */
126 virtual void proc();
127
128 /**
129 * @brief Set the active text-render font.
130 * @param fontPath Path to a TTF font file.
131 * @param fontSize Font point size.
132 */
133 void setFont(const std::string &fontPath, int fontSize = 24);
134
135 /**
136 * @brief Queue a text string for rendering during the current frame.
137 * @param text UTF-8 text.
138 * @param x Pixel X coordinate.
139 * @param y Pixel Y coordinate.
140 * @param col Text color.
141 */
142 void printText(const std::string &text, int x, int y, const SDL_Color &col);
143 void printText(const std::string &text, int x, int y, const SDL_Color &col, TTF_Font *font);
144 void printText(const std::string &text, int x, int y, const SDL_Color &col, const Font &font);
145
146 /** @brief Clear all queued text draw calls for the current frame. */
147 void clearTextQueue();
148
149 /**
150 * @brief Set the per-frame color attachment clear color.
151 * @param r Red channel [0, 1].
152 * @param g Green channel [0, 1].
153 * @param b Blue channel [0, 1].
154 * @param a Alpha channel [0, 1].
155 */
156 void setClearColor(float r, float g, float b, float a = 1.0f);
157
158 /** @brief Enable or disable F10 screenshot capture. */
159 void setEnableScreenshot(bool enabled) noexcept { screenshot_enabled = enabled; }
160
161 /** @brief Check whether F10 screenshot capture is enabled. */
162 [[nodiscard]] bool screenshotEnabled() const noexcept { return screenshot_enabled; }
163
164 /** @brief Get the underlying SDL window handle. */
165 [[nodiscard]] SDL_Window *getSDLWindow() const noexcept { return window.get(); }
166
167 /** @brief Get the Vulkan logical device handle. */
168 [[nodiscard]] VkDevice getDevice() const noexcept { return device; }
169
170 /** @brief Get the Vulkan physical device handle. */
171 [[nodiscard]] VkPhysicalDevice getPhysicalDevice() const noexcept { return physical_device; }
172
173 /** @brief Get the graphics queue handle. */
174 [[nodiscard]] VkQueue getGraphicsQueue() const noexcept { return graphics_queue; }
175
176 /** @brief Get the command pool used for graphics/upload work. */
177 [[nodiscard]] VkCommandPool getCommandPool() const noexcept { return command_pool; }
178
179 /** @brief Get the persistent Vulkan pipeline cache used by framework pipelines. */
180 [[nodiscard]] VkPipelineCache getPipelineCache() const noexcept { return pipeline_cache; }
181
182 /** @brief Get the swapchain color format. */
183 [[nodiscard]] VkFormat getSwapchainFormat() const noexcept { return swapchain_format; }
184
185 /** @brief Get the current swapchain extent. */
186 [[nodiscard]] VkExtent2D getSwapchainExtent() const noexcept { return swapchain_extent; }
187
188 /** @brief Get the depth format used for dynamic rendering attachments. */
189 [[nodiscard]] VkFormat getDepthFormat() const noexcept { return depth_format; }
190
191 /** @brief Get the number of swapchain images currently allocated. */
192 [[nodiscard]] size_t getSwapchainImageCount() const noexcept { return swapchain_images.size(); }
193
194 /**
195 * @brief Ensure deferred render resources are initialized.
196 * @return true when swapchain, command pool, and sync objects are ready.
197 */
199
200 /**
201 * @brief Return transient Vulkan command-pool allocations to the driver when supported.
202 *
203 * MXVK currently uses direct Vulkan memory allocations rather than VMA, so VMA
204 * defragmentation is not applicable. This hook schedules the available Vulkan
205 * memory maintenance operation and is safe to call during idle/loading points.
206 */
207 void trimMemory();
208
209 /**
210 * @brief Measure text dimensions in pixels.
211 * @param text Text string to measure.
212 * @param width Output width in pixels.
213 * @param height Output height in pixels.
214 * @return true when measurement succeeded.
215 */
216 [[nodiscard]] bool getTextDimensions(const std::string &text, int &width, int &height);
217 [[nodiscard]] bool getTextDimensions(const std::string &text, int &width, int &height, TTF_Font *font);
218 [[nodiscard]] bool getTextDimensions(const std::string &text, int &width, int &height, const Font &font);
219
220 /**
221 * @brief Create a sprite from a PNG file and register it with this window.
222 * @param pngPath Path to the PNG file.
223 * @param vertexShaderPath Optional custom vertex shader SPIR-V path.
224 * @param fragmentShaderPath Optional custom fragment shader SPIR-V path.
225 * @return Non-owning pointer to the created sprite.
226 */
227 VK_Sprite *createSprite(const std::string &pngPath, const std::string &vertexShaderPath = "", const std::string &fragmentShaderPath = "");
228
229 /**
230 * @brief Create a sprite from an SDL surface and register it with this window.
231 * @param surface Source surface pointer.
232 * @param vertexShaderPath Optional custom vertex shader SPIR-V path.
233 * @param fragmentShaderPath Optional custom fragment shader SPIR-V path.
234 * @return Non-owning pointer to the created sprite.
235 */
236 VK_Sprite *createSprite(SDL_Surface *surface, const std::string &vertexShaderPath = "", const std::string &fragmentShaderPath = "");
237
238 /**
239 * @brief Create a blank sprite texture and register it with this window.
240 * @param width Texture width in pixels.
241 * @param height Texture height in pixels.
242 * @param vertexShaderPath Optional custom vertex shader SPIR-V path.
243 * @param fragmentShaderPath Optional custom fragment shader SPIR-V path.
244 * @return Non-owning pointer to the created sprite.
245 */
246 VK_Sprite *createSprite(int width, int height, const std::string &vertexShaderPath = "", const std::string &fragmentShaderPath = "");
247
249 std::string fragmentShaderPath{};
250 std::array<float, 4> params{};
251 bool timeEnabled = false;
252 };
253
254 /**
255 * @brief Attach a full-screen post-processing fragment shader.
256 *
257 * The window renders the normal scene into an offscreen color target, then draws that
258 * target through the supplied sprite-compatible fragment shader into the swapchain.
259 * Shader params are passed through the existing sprite push-constant vec4.
260 *
261 * @param fragmentShaderPath Post-process fragment shader SPIR-V path.
262 * @param p1 First shader parameter.
263 * @param p2 Second shader parameter.
264 * @param p3 Third shader parameter.
265 * @param p4 Fourth shader parameter.
266 * @return Non-owning pointer to the internal post-process sprite for advanced setup.
267 */
268 VK_Sprite *attachPostProcessingShader(const std::string &fragmentShaderPath, float p1 = 0.0f, float p2 = 0.0f, float p3 = 0.0f, float p4 = 0.0f);
269 std::vector<VK_Sprite *> attachPostProcessingShaders(const std::vector<PostProcessingEffect> &effects);
270
271 /** @brief Detach the current post-processing shader and return to direct swapchain rendering. */
273
274 /** @brief Set the post-processing shader params passed as a vec4 push constant. */
275 void setPostProcessingShaderParams(float p1 = 0.0f, float p2 = 0.0f, float p3 = 0.0f, float p4 = 0.0f);
276 void setPostProcessingShaderParams(size_t effectIndex, float p1 = 0.0f, float p2 = 0.0f, float p3 = 0.0f, float p4 = 0.0f);
277
278 /** @brief Keep shader param 1 updated with elapsed render time in seconds. */
279 void setPostProcessingShaderTimeEnabled(bool enabled);
280 void setPostProcessingShaderTimeEnabled(size_t effectIndex, bool enabled);
281
282 void enablePostProcessing(VK_Sprite *sprite);
283
284 void setPostProcessingEnabled(bool enabled) { post_process_enabled = enabled; }
285
286 /**
287 * @brief Create a world-space billboard sprite from a PNG file.
288 * @param pngPath Path to the PNG file.
289 * @param vertexShaderPath Optional custom vertex shader SPIR-V path.
290 * @param fragmentShaderPath Optional custom fragment shader SPIR-V path.
291 * @return Non-owning pointer to the created 3D sprite batch.
292 */
293 VK_Sprite3D *createSprite3D(const std::string &pngPath, const std::string &vertexShaderPath = "", const std::string &fragmentShaderPath = "");
294
295 /**
296 * @brief Create a world-space billboard sprite from an SDL surface.
297 * @param surface Source surface pointer.
298 * @param vertexShaderPath Optional custom vertex shader SPIR-V path.
299 * @param fragmentShaderPath Optional custom fragment shader SPIR-V path.
300 * @return Non-owning pointer to the created 3D sprite batch.
301 */
302 VK_Sprite3D *createSprite3D(SDL_Surface *surface, const std::string &vertexShaderPath = "", const std::string &fragmentShaderPath = "");
303
304 /**
305 * @brief Check whether Vulkan validation layers are currently enabled.
306 * @return true if validation layers are enabled, false otherwise.
307 */
308 [[nodiscard]] bool validationEnabled() const;
309
310 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, [[maybe_unused]] void *user_data);
311
312 void showCursor(bool on);
313
314 VulkanContext context() const;
315
316 protected:
317 /**
318 * @brief Load a SPIR-V file from disk.
319 * @param path Absolute or relative path to a .spv file.
320 * @return Raw bytes loaded from file.
321 * @throws mxvk::Exception when the file cannot be opened, is empty, or is not 4-byte aligned.
322 */
323 static std::vector<char> loadSpv(const std::string &path);
324
325 /**
326 * @brief Create a shader module from SPIR-V bytecode.
327 * @param device Logical Vulkan device used to create the module.
328 * @param spv_bytes SPIR-V bytecode payload.
329 * @return Created shader module handle.
330 * @throws mxvk::Exception when inputs are invalid or module creation fails.
331 */
332 static VkShaderModule createShaderModule(VkDevice device, const std::vector<char> &spv_bytes);
333
334 /**
335 * @brief Initialize SDL window resources.
336 * @param title Window title string.
337 * @param width Window width in pixels.
338 * @param height Window height in pixels.
339 * @param flags Additional SDL window creation flags.
340 * @return true on success, false otherwise.
341 */
342 bool initWindow(const std::string &title, int width, int height, SDL_WindowFlags flags);
343
344 /**
345 * @brief Pick a suitable Vulkan physical device.
346 */
347 void pickDevice();
348
349 /**
350 * @brief Create a logical Vulkan device from the selected physical device.
351 */
352 void createLogicalDevice();
353
354 /**
355 * @brief Create final device resources.
356 */
357 void createDevice();
358
359 /**
360 * @brief Request loop termination.
361 */
362 void exit();
363
364 /**
365 * @brief Called right before swapchain-dependent resources are recreated.
366 *
367 * Derived classes can release swapchain-dependent resources here.
368 */
369 virtual void onSwapchainAboutToRecreate();
370
371 /**
372 * @brief Called after swapchain and render resources are recreated.
373 *
374 * Derived classes can rebuild swapchain-dependent resources here.
375 */
376 virtual void onSwapchainRecreated();
377
378 /**
379 * @brief Optional hook for derived classes to record extra draw commands.
380 *
381 * This callback is invoked inside the dynamic-rendering scope started by
382 * the window, after viewport/scissor are configured and before rendering ends.
383 *
384 * @param cmd Active command buffer in recording state.
385 * @param image_index Current swapchain image index.
386 */
387 virtual void onRecordCustomRendering(VkCommandBuffer cmd, uint32_t image_index);
388
389 /**
390 * @brief Allow derived classes to customize depth/stencil attachments for the main dynamic rendering pass.
391 *
392 * Override this when custom rendering needs hardware stencil testing or a custom depth/stencil image.
393 * The callback is invoked immediately before vkCmdBeginRendering.
394 */
395 virtual void onConfigureDepthStencilAttachments(VkRenderingAttachmentInfo &depth_attachment,
396 VkRenderingAttachmentInfo &stencil_attachment,
397 uint32_t image_index);
398
399 protected:
400 /**
401 * @brief Capture the most recently presented swapchain image as tightly packed RGBA8 pixels.
402 *
403 * This performs a synchronous GPU readback and may briefly stall rendering.
404 */
405 void captureSnapshotPixels(std::vector<std::uint8_t> &rgba_pixels, uint32_t &width, uint32_t &height);
406
407 /**
408 * @brief Render one standalone sprite using the window's shared sprite pipeline.
409 *
410 * This is intended for derived classes that want to draw a sprite before or after
411 * their own scene content without registering it in the window-managed sprite list.
412 */
413 void renderStandaloneSprite(VK_Sprite &sprite, VkCommandBuffer cmd);
414
415 private:
416 static constexpr uint32_t invalid_queue_index = std::numeric_limits<uint32_t>::max();
417 static constexpr uint32_t max_frames_in_flight = 2;
418
419 static constexpr const char *validation_layer_name = "VK_LAYER_KHRONOS_validation";
420
421 struct SwapchainSupport {
422 VkSurfaceCapabilitiesKHR capabilities{};
423 std::vector<VkSurfaceFormatKHR> formats{};
424 std::vector<VkPresentModeKHR> present_modes{};
425 };
426
427 static SwapchainSupport querySwapchainSupport(VkPhysicalDevice device, VkSurfaceKHR surface);
428 static VkSurfaceFormatKHR chooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &available_formats);
429 VkPresentModeKHR choosePresentMode(const std::vector<VkPresentModeKHR> &available_present_modes) const;
430 static VkExtent2D chooseExtent(const VkSurfaceCapabilitiesKHR &capabilities, SDL_Window *window);
431 static bool hasValidationLayerSupport();
432 static std::optional<VkDebugUtilsMessengerCreateInfoEXT> makeDebugMessengerCreateInfo();
433 void setupDebugMessenger();
434 void cleanupDebugMessenger();
435 bool createSwapchain(VkSwapchainKHR old_swapchain);
436 bool createRenderResources();
437 bool createSyncObjects();
438 void cleanupSyncObjects();
439 void cleanupSwapchain(bool preserveCommandPool = true);
440 void recreateSwapchain();
441 void drawFrame();
442 [[nodiscard]] std::string pipelineCachePath() const;
443 void createPipelineCache();
444 void savePipelineCache() const;
445 void destroyPipelineCache();
446 [[nodiscard]] std::string resolveRuntimeShaderPath(const std::string &shaderFileName, const char *fallbackDir) const;
447 void createSpriteDescriptorSetLayout();
448 void createSpritePipeline();
449 void destroySpritePipeline();
450 void createPostProcessTargets();
451 void destroyPostProcessTargets();
452 void ensureTextRenderer();
453 void createTextDescriptorSetLayout();
454 void createTextPipeline();
455 void destroyTextPipeline();
456 void maybeTrimMemory();
457 void saveScreenshot();
458 [[nodiscard]] std::string makeScreenshotPath();
459 void enqueueScreenshotSave(std::string path, std::vector<std::uint8_t> rgba, uint32_t width, uint32_t height);
460 void startScreenshotWorker();
461 void stopScreenshotWorker();
462 void screenshotWorkerLoop();
463 [[nodiscard]] bool isPostProcessSprite(const VK_Sprite *sprite) const;
464 [[nodiscard]] std::string resolveDefaultFontPath() const;
465 void ensureTextRenderer(const std::string &fallbackFontPath, int fallbackFontSize);
466 void toggleFpsCounter();
467 void updateFpsCounter();
468
469 protected:
470 // Protected state allows subclasses to implement custom rendering paths.
471
473 void operator()(SDL_Window *ptr) const {
474 if (ptr != nullptr) {
475 SDL_DestroyWindow(ptr);
476 }
477 }
478 };
479
480 std::unique_ptr<SDL_Window, SDLWindowDeleter> window{};
481 VkInstance instance = VK_NULL_HANDLE;
482 VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE;
483 VkSurfaceKHR surface = VK_NULL_HANDLE;
484 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
485 VkDevice device = VK_NULL_HANDLE;
486 uint32_t graphics_queue_family = invalid_queue_index;
487 uint32_t present_queue_family = invalid_queue_index;
488 VkQueue graphics_queue = VK_NULL_HANDLE;
489 VkQueue present_queue = VK_NULL_HANDLE;
490 VkPipelineCache pipeline_cache = VK_NULL_HANDLE;
491
492 VkSwapchainKHR swapchain = VK_NULL_HANDLE;
493 VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
494 VkFormat depth_format = VK_FORMAT_UNDEFINED;
495 VkExtent2D swapchain_extent{};
496 std::vector<VkImage> swapchain_images{};
497 std::vector<VkImageView> swapchain_image_views{};
498 std::vector<bool> swapchain_image_initialized{};
499 std::vector<VkImage> depth_images{};
500 std::vector<VkDeviceMemory> depth_image_memories{};
501 std::vector<VkImageView> depth_image_views{};
502 std::vector<bool> depth_image_initialized{};
503
504 VkCommandPool command_pool = VK_NULL_HANDLE;
505 std::vector<VkCommandBuffer> command_buffers{};
506
507 std::array<VkSemaphore, max_frames_in_flight> image_available{};
508 std::vector<VkSemaphore> render_finished{};
509 std::array<VkFence, max_frames_in_flight> in_flight_fences{};
510 std::vector<VkFence> image_fences{};
511 uint32_t current_frame = 0;
512 uint32_t last_presented_image_index = invalid_queue_index;
514
515 bool sdl_initialized = false;
516 bool active = false;
519 uint32_t screenshot_index = 0;
521 std::string path;
522 std::vector<std::uint8_t> rgba;
523 uint32_t width = 0;
524 uint32_t height = 0;
525 };
527 std::condition_variable screenshot_queue_cv;
528 std::deque<ScreenshotSaveTask> screenshot_save_queue;
529 std::thread screenshot_worker;
531 bool validation_enabled = false;
536 static constexpr uint64_t resize_settle_delay_ms = 150;
537 std::chrono::steady_clock::time_point last_memory_trim_time = std::chrono::steady_clock::now();
538 static constexpr std::chrono::seconds MEMORY_TRIM_INTERVAL{30};
539
540 std::vector<std::unique_ptr<VK_Sprite>> sprites{};
541 std::vector<std::unique_ptr<VK_Sprite3D>> sprites3d{};
542 VkDescriptorSetLayout sprite_descriptor_set_layout = VK_NULL_HANDLE;
543 VkPipelineLayout sprite_pipeline_layout = VK_NULL_HANDLE;
544 VkPipeline sprite_pipeline = VK_NULL_HANDLE;
545 bool sprite_state_dirty = false;
550 std::array<float, 4> post_process_params{};
551 std::chrono::steady_clock::time_point post_process_start_time = std::chrono::steady_clock::now();
552 std::vector<VK_Sprite *> post_process_sprites{};
553 std::vector<VK_Sprite *> owned_post_process_sprites{};
554 std::vector<std::array<float, 4>> post_process_effect_params{};
556 std::vector<std::chrono::steady_clock::time_point> post_process_effect_start_times{};
557 std::vector<std::vector<VkImage>> post_process_images{};
558 std::vector<std::vector<VkDeviceMemory>> post_process_memories{};
559 std::vector<std::vector<VkImageView>> post_process_views{};
560 std::vector<std::vector<bool>> post_process_initialized{};
561
562 std::unique_ptr<VK_Text> text_renderer{};
563 VkDescriptorSetLayout text_descriptor_set_layout = VK_NULL_HANDLE;
564 VkPipelineLayout text_pipeline_layout = VK_NULL_HANDLE;
565 VkPipeline text_pipeline = VK_NULL_HANDLE;
566 bool text_state_dirty = false;
567 bool font_configured = false;
568 std::string font_path{};
569 int font_size = 24;
573 std::chrono::steady_clock::time_point fps_counter_sample_time{};
575 std::string fps_counter_text = "FPS: --";
576 VkClearColorValue clear_color{{0.0f, 0.0f, 0.0f, 1.0f}};
577 std::vector<VkSwapchainKHR> retired_swapchains;
578 };
579
580} // namespace mxvk
Small RAII wrapper for an SDL_ttf font handle.
Definition mxvk_text.hpp:46
Depth-tested 3D billboard sprite batch.
VkPipelineLayout sprite_pipeline_layout
Definition mxvk.hpp:543
bool post_process_enabled
Definition mxvk.hpp:548
bool force_swapchain_recreate
Definition mxvk.hpp:534
VkExtent2D getSwapchainExtent() const noexcept
Get the current swapchain extent.
Definition mxvk.hpp:186
std::mutex screenshot_queue_mutex
Definition mxvk.hpp:526
void showCursor(bool on)
Definition mxvk.cpp:3633
VkSwapchainKHR swapchain
Definition mxvk.hpp:492
void captureSnapshotPixels(std::vector< std::uint8_t > &rgba_pixels, uint32_t &width, uint32_t &height)
Capture the most recently presented swapchain image as tightly packed RGBA8 pixels.
Definition mxvk.cpp:800
virtual void event(SDL_Event &e)
Handle one SDL event.
Definition mxvk.cpp:582
bool screenshotEnabled() const noexcept
Check whether F10 screenshot capture is enabled.
Definition mxvk.hpp:162
virtual ~VK_Window()
Destroy owned Vulkan and SDL resources.
Definition mxvk.cpp:213
void pickDevice()
Pick a suitable Vulkan physical device.
Definition mxvk.cpp:1427
static constexpr std::chrono::seconds MEMORY_TRIM_INTERVAL
Definition mxvk.hpp:538
VkDescriptorSetLayout sprite_descriptor_set_layout
Definition mxvk.hpp:542
std::vector< std::vector< bool > > post_process_initialized
Definition mxvk.hpp:560
void loop()
Run the main event/render loop.
Definition mxvk.cpp:600
VK_Sprite3D * createSprite3D(const std::string &pngPath, const std::string &vertexShaderPath="", const std::string &fragmentShaderPath="")
Create a world-space billboard sprite from a PNG file.
Definition mxvk.cpp:3578
std::condition_variable screenshot_queue_cv
Definition mxvk.hpp:527
VkDevice getDevice() const noexcept
Get the Vulkan logical device handle.
Definition mxvk.hpp:168
VkDebugUtilsMessengerEXT debug_messenger
Definition mxvk.hpp:482
VkDevice device
Definition mxvk.hpp:485
static VkBool32 debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
Definition mxvk.cpp:44
std::chrono::steady_clock::time_point fps_counter_sample_time
Definition mxvk.hpp:573
uint32_t screenshot_index
Definition mxvk.hpp:519
void createLogicalDevice()
Create a logical Vulkan device from the selected physical device.
Definition mxvk.cpp:1514
uint32_t fps_counter_frame_count
Definition mxvk.hpp:574
virtual bool initVulkan(bool validiation)
Initialize Vulkan state.
Definition mxvk.cpp:318
VK_Sprite * createSprite(const std::string &pngPath, const std::string &vertexShaderPath="", const std::string &fragmentShaderPath="")
Create a sprite from a PNG file and register it with this window.
Definition mxvk.cpp:3477
VkClearColorValue clear_color
Definition mxvk.hpp:576
VkQueue getGraphicsQueue() const noexcept
Get the graphics queue handle.
Definition mxvk.hpp:174
std::string screenshot_prefix
Definition mxvk.hpp:518
virtual void onSwapchainRecreated()
Called after swapchain and render resources are recreated.
Definition mxvk.cpp:1132
VkInstance instance
Definition mxvk.hpp:481
VkFormat swapchain_format
Definition mxvk.hpp:493
VkCommandPool getCommandPool() const noexcept
Get the command pool used for graphics/upload work.
Definition mxvk.hpp:177
VkExtent2D swapchain_extent
Definition mxvk.hpp:495
virtual void onSwapchainAboutToRecreate()
Called right before swapchain-dependent resources are recreated.
Definition mxvk.cpp:1130
std::vector< bool > post_process_effect_time_enabled
Definition mxvk.hpp:555
VulkanContext context() const
Definition mxvk.cpp:59
bool validation_enabled
Definition mxvk.hpp:531
bool screenshot_worker_stop
Definition mxvk.hpp:530
std::vector< std::array< float, 4 > > post_process_effect_params
Definition mxvk.hpp:554
std::vector< std::vector< VkDeviceMemory > > post_process_memories
Definition mxvk.hpp:558
VkDescriptorSetLayout text_descriptor_set_layout
Definition mxvk.hpp:563
static constexpr uint64_t resize_settle_delay_ms
Definition mxvk.hpp:536
std::vector< std::vector< VkImageView > > post_process_views
Definition mxvk.hpp:559
VkPipeline text_pipeline
Definition mxvk.hpp:565
std::chrono::steady_clock::time_point post_process_start_time
Definition mxvk.hpp:551
VkFormat depth_format
Definition mxvk.hpp:494
uint32_t present_queue_family
Definition mxvk.hpp:487
void enablePostProcessing(VK_Sprite *sprite)
Definition mxvk.cpp:1271
uint32_t last_presented_image_index
Definition mxvk.hpp:512
std::vector< VkImageView > swapchain_image_views
Definition mxvk.hpp:497
std::vector< VK_Sprite * > owned_post_process_sprites
Definition mxvk.hpp:553
static VkShaderModule createShaderModule(VkDevice device, const std::vector< char > &spv_bytes)
Create a shader module from SPIR-V bytecode.
Definition mxvk.cpp:145
std::chrono::steady_clock::time_point last_memory_trim_time
Definition mxvk.hpp:537
VkQueue present_queue
Definition mxvk.hpp:489
void createDevice()
Create final device resources.
Definition mxvk.cpp:1645
bool text_state_dirty
Definition mxvk.hpp:566
Font fps_counter_font
Definition mxvk.hpp:572
bool getTextDimensions(const std::string &text, int &width, int &height)
Measure text dimensions in pixels.
Definition mxvk.cpp:3069
VK_Window & operator=(const VK_Window &)=delete
std::vector< bool > swapchain_image_initialized
Definition mxvk.hpp:498
std::vector< VkImage > swapchain_images
Definition mxvk.hpp:496
std::vector< VkFence > image_fences
Definition mxvk.hpp:510
std::string font_path
Definition mxvk.hpp:568
void clearTextQueue()
Clear all queued text draw calls for the current frame.
Definition mxvk.cpp:3063
size_t getSwapchainImageCount() const noexcept
Get the number of swapchain images currently allocated.
Definition mxvk.hpp:192
std::vector< VkSwapchainKHR > retired_swapchains
Definition mxvk.hpp:577
std::vector< VkImageView > depth_image_views
Definition mxvk.hpp:501
VK_Window & operator=(VK_Window &&)=delete
virtual void onConfigureDepthStencilAttachments(VkRenderingAttachmentInfo &depth_attachment, VkRenderingAttachmentInfo &stencil_attachment, uint32_t image_index)
Allow derived classes to customize depth/stencil attachments for the main dynamic rendering pass.
Definition mxvk.cpp:1138
bool post_process_time_enabled
Definition mxvk.hpp:549
SDL_Window * getSDLWindow() const noexcept
Get the underlying SDL window handle.
Definition mxvk.hpp:165
std::unique_ptr< VK_Text > text_renderer
Definition mxvk.hpp:562
bool screenshot_enabled
Definition mxvk.hpp:517
void saveSnapshot(const std::string &path)
Save the most recently rendered window contents as a PNG file.
Definition mxvk.cpp:782
uint32_t graphics_queue_family
Definition mxvk.hpp:486
void setClearColor(float r, float g, float b, float a=1.0f)
Set the per-frame color attachment clear color.
Definition mxvk.cpp:593
std::vector< VK_Sprite * > attachPostProcessingShaders(const std::vector< PostProcessingEffect > &effects)
Definition mxvk.cpp:1159
virtual void onPrepareFrameRendering(VkCommandBuffer cmd, uint32_t image_index)
Record resource transitions that must happen before dynamic rendering begins.
Definition mxvk.cpp:1134
std::vector< VkCommandBuffer > command_buffers
Definition mxvk.hpp:505
void renderStandaloneSprite(VK_Sprite &sprite, VkCommandBuffer cmd)
Render one standalone sprite using the window's shared sprite pipeline.
Definition mxvk.cpp:1142
std::thread screenshot_worker
Definition mxvk.hpp:529
uint32_t current_frame
Definition mxvk.hpp:511
std::vector< VkSemaphore > render_finished
Definition mxvk.hpp:508
VkPipelineCache pipeline_cache
Definition mxvk.hpp:490
std::unique_ptr< SDL_Window, SDLWindowDeleter > window
Definition mxvk.hpp:480
bool sdl_initialized
Definition mxvk.hpp:515
std::vector< std::chrono::steady_clock::time_point > post_process_effect_start_times
Definition mxvk.hpp:556
VkPipeline sprite_pipeline
Definition mxvk.hpp:544
void exit()
Request loop termination.
Definition mxvk.cpp:1126
VkCommandPool command_pool
Definition mxvk.hpp:504
VK_Sprite * attachPostProcessingShader(const std::string &fragmentShaderPath, float p1=0.0f, float p2=0.0f, float p3=0.0f, float p4=0.0f)
Attach a full-screen post-processing fragment shader.
Definition mxvk.cpp:1154
VK_Window(VK_Window &&)=delete
bool ensureRenderResources()
Ensure deferred render resources are initialized.
Definition mxvk.cpp:1406
VkSurfaceKHR surface
Definition mxvk.hpp:483
VK_Window()=default
Construct an empty window object.
VkPhysicalDevice physical_device
Definition mxvk.hpp:484
VkPipelineLayout text_pipeline_layout
Definition mxvk.hpp:564
virtual void onRecordCustomRendering(VkCommandBuffer cmd, uint32_t image_index)
Optional hook for derived classes to record extra draw commands.
Definition mxvk.cpp:1136
std::array< float, 4 > post_process_params
Definition mxvk.hpp:550
void detachPostProcessingShader()
Detach the current post-processing shader and return to direct swapchain rendering.
Definition mxvk.cpp:1198
std::vector< bool > depth_image_initialized
Definition mxvk.hpp:502
bool fps_counter_font_ready
Definition mxvk.hpp:571
VkFormat getDepthFormat() const noexcept
Get the depth format used for dynamic rendering attachments.
Definition mxvk.hpp:189
VkPipelineCache getPipelineCache() const noexcept
Get the persistent Vulkan pipeline cache used by framework pipelines.
Definition mxvk.hpp:180
std::deque< ScreenshotSaveTask > screenshot_save_queue
Definition mxvk.hpp:528
void release()
Release Vulkan and SDL resources.
Definition mxvk.cpp:218
void setFont(const std::string &fontPath, int fontSize=24)
Set the active text-render font.
Definition mxvk.cpp:2991
void setPostProcessingEnabled(bool enabled)
Definition mxvk.hpp:284
std::vector< VkDeviceMemory > depth_image_memories
Definition mxvk.hpp:500
PresentModePreference present_mode_preference
Definition mxvk.hpp:532
void printText(const std::string &text, int x, int y, const SDL_Color &col)
Queue a text string for rendering during the current frame.
Definition mxvk.cpp:3018
static std::vector< char > loadSpv(const std::string &path)
Load a SPIR-V file from disk.
Definition mxvk.cpp:141
std::vector< std::unique_ptr< VK_Sprite3D > > sprites3d
Definition mxvk.hpp:541
std::vector< VK_Sprite * > post_process_sprites
Definition mxvk.hpp:552
bool sprite_state_dirty
Definition mxvk.hpp:545
void trimMemory()
Return transient Vulkan command-pool allocations to the driver when supported.
Definition mxvk.cpp:1041
VK_Sprite * post_process_sprite
Definition mxvk.hpp:546
bool framebuffer_resized
Definition mxvk.hpp:533
VkQueue graphics_queue
Definition mxvk.hpp:488
bool font_configured
Definition mxvk.hpp:567
void setPostProcessingShaderParams(float p1=0.0f, float p2=0.0f, float p3=0.0f, float p4=0.0f)
Set the post-processing shader params passed as a vec4 push constant.
Definition mxvk.cpp:1227
std::string fps_counter_text
Definition mxvk.hpp:575
virtual void render()
Render one frame.
Definition mxvk.cpp:778
bool initWindow(const std::string &title, int width, int height, SDL_WindowFlags flags)
Initialize SDL window resources.
Definition mxvk.cpp:1059
std::vector< VkImage > depth_images
Definition mxvk.hpp:499
virtual void proc()
Execute one processing/update step.
Definition mxvk.cpp:1038
bool validationEnabled() const
Check whether Vulkan validation layers are currently enabled.
Definition mxvk.cpp:2911
VK_Window(const VK_Window &)=delete
std::vector< std::unique_ptr< VK_Sprite > > sprites
Definition mxvk.hpp:540
uint64_t last_resize_event_ms
Definition mxvk.hpp:535
VkPhysicalDevice getPhysicalDevice() const noexcept
Get the Vulkan physical device handle.
Definition mxvk.hpp:171
void setPostProcessingShaderTimeEnabled(bool enabled)
Keep shader param 1 updated with elapsed render time in seconds.
Definition mxvk.cpp:1248
std::vector< std::vector< VkImage > > post_process_images
Definition mxvk.hpp:557
void setEnableScreenshot(bool enabled) noexcept
Enable or disable F10 screenshot capture.
Definition mxvk.hpp:159
VK_Sprite * owned_post_process_sprite
Definition mxvk.hpp:547
std::array< VkSemaphore, max_frames_in_flight > image_available
Definition mxvk.hpp:507
bool fps_counter_enabled
Definition mxvk.hpp:570
bool swapchain_supports_transfer_src
Definition mxvk.hpp:513
std::array< VkFence, max_frames_in_flight > in_flight_fences
Definition mxvk.hpp:509
VkFormat getSwapchainFormat() const noexcept
Get the swapchain color format.
Definition mxvk.hpp:183
Minimal Vulkan handles shared across MXVK helpers.
World-space textured billboard renderer for MXVK dynamic rendering.
Vulkan 2-D sprite renderer with optional custom shaders and instancing.
Vulkan SDL_ttf text renderer.
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30
bool defaultEnableScreenshot()
const std::string & defaultExecutableName()
std::array< float, 4 > params
Definition mxvk.hpp:250
void operator()(SDL_Window *ptr) const
Definition mxvk.hpp:473
std::vector< std::uint8_t > rgba
Definition mxvk.hpp:522
Minimal Vulkan handles required by MXVK resource helpers.