libmx2 2.2.1
C++20 multimedia and game-engine library (SDL2 / OpenGL / Vulkan)
Loading...
Searching...
No Matches
vk.hpp
Go to the documentation of this file.
1/**
2 * @file vk.hpp
3 * @brief Vulkan application window and supporting structs for libmx.
4 *
5 * Provides VKWindow, the primary Vulkan rendering window, along with
6 * supporting data structures (Vertex, QueueFamilyIndices,
7 * SwapChainSupportDetails, UniformBufferObject). Sprite and text
8 * rendering are delegated to VKSprite and VKText respectively.
9 */
10#ifndef _VK_MX_H__
11#define _VK_MX_H__
12#include"config.h"
13#ifndef WITH_MOLTEN
14#include "volk.h"
15#include <SDL_vulkan.h>
16#else
17#include <SDL_vulkan.h>
18#include<vulkan/vulkan.h>
19#endif
20#include"exception.hpp"
21#include "util.hpp"
22
23#include "vk_text.hpp"
24#include "vk_sprite.hpp"
25#include <iostream>
26#include <stdexcept>
27#include <cstdlib>
28#include <vector>
29#include <optional>
30#include <set>
31#include <fstream>
32#include <algorithm>
33#include <array>
34#include <cmath>
35#include <glm/glm.hpp>
36#include <glm/gtc/matrix_transform.hpp>
37#include <glm/gtc/type_ptr.hpp>
38#include <map>
39#include <utility>
40#include <SDL_ttf.h>
41#include <memory>
42
43#ifndef M_PI
44#define M_PI 3.14159265358979323846
45#endif
46
47#define VK_CHECK_RESULT(f) { \
48 VkResult res = (f); \
49 if (res != VK_SUCCESS) { \
50 throw mx::Exception("Fatal : VkResult is \"" + std::to_string(res) + "\" in " + __FILE__ + " at line " + std::to_string(__LINE__)); \
51 } \
52}
53
54namespace mx {
55
56 class VKAbstractModel;
57
58/**
59 * @struct Vertex
60 * @brief Per-vertex data sent to the Vulkan vertex buffer.
61 */
62 struct Vertex {
63 float pos[3]; ///< 3-D position (x, y, z).
64 float texCoord[2]; ///< UV texture coordinates.
65 float normal[3]; ///< Surface normal vector.
66 };
67
68/**
69 * @struct QueueFamilyIndices
70 * @brief Tracks Vulkan queue family assignments needed to create a device.
71 */
73 std::optional<uint32_t> graphicsFamily; ///< Index of the graphics queue family.
74 std::optional<uint32_t> presentFamily; ///< Index of the presentation queue family.
75
76 /**
77 * @brief Check whether both required families have been found.
78 * @return @c true if graphics and present families are both assigned.
79 */
80 bool isComplete() {
81 return graphicsFamily.has_value() && presentFamily.has_value();
82 }
83 };
84
85/**
86 * @struct SwapChainSupportDetails
87 * @brief Swapchain capabilities and format/mode candidates for a physical device.
88 */
90 VkSurfaceCapabilitiesKHR capabilities; ///< Surface capability limits.
91 std::vector<VkSurfaceFormatKHR> formats; ///< Supported colour formats.
92 std::vector<VkPresentModeKHR> presentModes; ///< Supported presentation modes.
93 };
94
95/**
96 * @struct UniformBufferObject
97 * @brief Standard UBO layout uploaded to shaders each frame.
98 *
99 * Provides model/view/projection matrices plus application-defined
100 * parameters and a colour tint.
101 */
103 alignas(16) glm::mat4 model; ///< Model transform matrix.
104 alignas(16) glm::mat4 view; ///< View (camera) matrix.
105 alignas(16) glm::mat4 proj; ///< Projection matrix.
106 alignas(16) glm::vec4 params; ///< Application-defined shader parameters.
107 alignas(16) glm::vec4 color; ///< Global colour tint.
108 };
109
110/**
111 * @class VKWindow
112 * @brief Primary Vulkan rendering window and device management class.
113 *
114 * Encapsulates the full Vulkan initialisation sequence: instance, surface,
115 * physical and logical device selection, swap chain creation, render pass,
116 * descriptor sets, command buffers, and synchronisation. Derived classes
117 * implement event() and optionally override draw(), initVulkan(), and
118 * cleanup() to add application-specific rendering.
119 *
120 * Built-in support for:
121 * - 2-D text rendering via VKText
122 * - Sprite rendering via VKSprite
123 * - Texture upload (SDL_Surface or raw pixels)
124 * - Wireframe toggle
125 */
126 class VKWindow {
127 public:
128 VKWindow() = default;
129
130 /**
131 * @brief Create and fully initialise the Vulkan window.
132 * @param title Window title string.
133 * @param width Width in pixels.
134 * @param height Height in pixels.
135 * @param full Start fullscreen if @c true.
136 * @param valid Enable Vulkan validation layers if @c true.
137 */
138 VKWindow(const std::string &title, int width, int height, bool full = false, bool valid = true);
139
140 /** @brief Virtual destructor — subclasses should call cleanup(). */
141 virtual ~VKWindow() { }
142 VKWindow(const VKWindow&) = delete;
143 VKWindow& operator=(const VKWindow&) = delete;
144 VKWindow(VKWindow&&) = delete;
146
147 friend class VKAbstractModel;
148
149 /**
150 * @brief Open the SDL2 window (called automatically by constructor).
151 * @param title Title string.
152 * @param width Width.
153 * @param height Height.
154 * @param full Fullscreen flag.
155 */
156 void initWindow(const std::string &title, int width, int height, bool full = false);
157
158 /**
159 * @brief Set the font used for printText().
160 * @param font Path to the TTF font file.
161 * @param size Point size.
162 */
163 void setFont(const std::string &font, const int size = 24);
164
165 /** @brief Initialise all Vulkan objects (overridable). */
166 virtual void initVulkan();
167
168 /** @brief Create and upload the vertex buffer. */
169 void createVertexBuffer();
170
171 /**
172 * @brief Set the asset root directory.
173 * @param path Asset directory path.
174 */
175 void setPath(const std::string &path);
176
177 /** @brief Run the blocking event/render loop. */
178 void loop();
179
180 /** @brief Process one event/render iteration (overridable). */
181 virtual void proc();
182
183 /** @brief Free all Vulkan resources (overridable). */
184 virtual void cleanup();
185
186 /**
187 * @brief Handle an SDL event (pure virtual).
188 * @param e SDL event to process.
189 */
190 virtual void event(SDL_Event &e) = 0;
191
192 /**
193 * @brief Record rendering commands for the current frame (overridable).
194 *
195 * The default implementation draws the main textured quad and updates
196 * the uniform buffer.
197 */
198 virtual void draw();
199
200 /** @brief Called when the window is resized (optional override). */
201 virtual void onResize() {}
202
203 /**
204 * @brief Control whether 3-D geometry is rendered this frame.
205 * @return @c true (default) to submit the 3-D render pass.
206 */
207 virtual bool shouldRender3D() { return true; }
208
209 /** @brief (Re)create the graphics pipeline. */
211
212 /**
213 * @brief Compile a SPIR-V shader module.
214 * @param code Byte vector of SPIR-V code.
215 * @return VkShaderModule handle.
216 */
217 VkShaderModule createShaderModule(const std::vector<char>& code);
218
219 int w = 0; ///< Current window width.
220 int h = 0; ///< Current window height.
221 mxUtil util; ///< Asset path and utility helpers.
222
223 /** @brief Post a quit event to stop the loop. */
224 void quit();
225
226 /**
227 * @brief Toggle fullscreen mode.
228 * @param full @c true for fullscreen.
229 */
230 void setFullScreen(const bool full);
231
232 /**
233 * @brief Replace the primary texture from an SDL_Surface.
234 * @param newSurface Source surface (not consumed).
235 */
236 void updateTexture(SDL_Surface* newSurface);
237
238 /**
239 * @brief Replace the primary texture from a raw pixel buffer.
240 * @param pixels Pointer to RGBA data.
241 * @param imageSize Size of the data in bytes.
242 */
243 void updateTexture(void* pixels, VkDeviceSize imageSize);
244
245 /**
246 * @brief Queue a text string for rendering at a screen position.
247 * @param text String to display.
248 * @param x X position in pixels.
249 * @param y Y position in pixels.
250 * @param col Text colour.
251 */
252 void printText(const std::string &text, int x, int y, const SDL_Color &col);
253
254 /** @brief Clear all pending text-render entries. */
255 void clearTextQueue();
256
257 /**
258 * @brief Measure a text string without rendering it.
259 * @param text String to measure.
260 * @param width Output: pixel width.
261 * @param height Output: pixel height.
262 * @return @c true if measurement succeeded.
263 */
264 bool getTextDimensions(const std::string &text, int& width, int& height);
265
266 /**
267 * @brief Create a sprite from a PNG file.
268 * @param pngPath Path to the PNG image.
269 * @param vertexShader Vertex shader file path.
270 * @param fragmentShaderPath Fragment shader file path (empty = default).
271 * @return Pointer to the created VKSprite (owned by this window).
272 */
273 VKSprite* createSprite(const std::string &pngPath, const std::string &vertexShader, const std::string &fragmentShaderPath = "");
274
275 /**
276 * @brief Create a sprite from an SDL_Surface.
277 * @param surface Source surface.
278 * @param vertexShader Vertex shader file path.
279 * @param fragmentShaderPath Fragment shader file path.
280 * @return Pointer to the created VKSprite.
281 */
282 VKSprite* createSprite(SDL_Surface* surface, const std::string &vertexShader, const std::string &fragmentShaderPath = "");
283
284 /**
285 * @brief Create a blank sprite of the given dimensions.
286 * @param width Pixel width.
287 * @param height Pixel height.
288 * @param vertexShader Vertex shader file path.
289 * @param fragmentShaderPath Fragment shader file path.
290 * @return Pointer to the created VKSprite.
291 */
292 VKSprite* createSprite(int width, int height, const std::string &vertexShader = "", const std::string &fragmentShaderPath = "");
293
294 /** @return Current window width. */
295 int getWidth() const { return w; }
296 /** @return Current window height. */
297 int getHeight() const { return h; }
298
299 /**
300 * @brief Resize the SDL window and recreate the swapchain.
301 * @param width New width.
302 * @param height New height.
303 */
304 void resizeWindow(int width, int height);
305
306 /**
307 * @brief Enable joystick and game controller subsystems on demand.
308 * @return @c true if controller input is ready, @c false on failure.
309 */
311
312 /** @return @c true if controller input subsystem was enabled. */
314
315 /**
316 * @brief Enable or disable wireframe rendering.
317 * @param enable @c true to draw in wireframe.
318 */
319 void setWireFrame(bool enable) { useWireFrame = enable; }
320 /** @return @c true if wireframe mode is active. */
321 bool getWireFrame() const { return useWireFrame; }
322 /** @return Vulkan physical device handle. */
323 VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; }
324 /** @return Vulkan logical device handle. */
325 VkDevice getDevice() const { return device; }
326 /** @return Vulkan graphics queue handle. */
327 VkQueue getGraphicsQueue() const { return graphicsQueue; }
328 /** @return Vulkan command pool handle. */
329 VkCommandPool getCommandPool() const { return commandPool; }
330 protected:
331 bool active = true; ///< @c true while the event loop should keep running.
332 bool inputControllersInitialized = false; ///< Whether joystick/controller input is enabled.
333 bool enableValidation = true; ///< Enable Vulkan validation layers.
334 std::string font = "font.ttf"; ///< Path to the current TTF font.
335 int font_size = 24; ///< Current font point size.
336 VkInstance instance = VK_NULL_HANDLE; ///< Vulkan instance.
337 VkSurfaceKHR surface = VK_NULL_HANDLE; ///< Window surface.
338 VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; ///< Selected GPU.
339 VkDevice device = VK_NULL_HANDLE; ///< Logical device.
340 VkQueue graphicsQueue = VK_NULL_HANDLE; ///< Graphics submission queue.
341 VkQueue presentQueue = VK_NULL_HANDLE; ///< Presentation queue.
342 VkDescriptorSetLayout descriptorSetLayout; ///< Main descriptor set layout.
343
344 VkSwapchainKHR swapChain = VK_NULL_HANDLE; ///< Active swapchain.
345 std::vector<VkImage> swapChainImages; ///< Swapchain image handles.
346 VkFormat swapChainImageFormat; ///< Colour format of swapchain images.
347 VkExtent2D swapChainExtent; ///< Swapchain pixel dimensions.
348 std::vector<VkImageView> swapChainImageViews; ///< Image views into swapchain images.
349 std::vector<VkBuffer> uniformBuffers; ///< Per-frame uniform buffers.
350 std::vector<VkDeviceMemory> uniformBuffersMemory; ///< Memory for per-frame UBOs.
351 std::vector<void*> uniformBuffersMapped; ///< Persistently mapped UBO pointers.
352
353 VkRenderPass renderPass = VK_NULL_HANDLE; ///< Main render pass.
354 VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; ///< Pipeline layout for the main pass.
355 VkPipeline graphicsPipeline = VK_NULL_HANDLE; ///< Filled-polygon graphics pipeline.
356 VkPipeline graphicsPipelineMatrix = VK_NULL_HANDLE; ///< 3-D matrix-enabled graphics pipeline.
357 VkPolygonMode currentPolygonMode = VK_POLYGON_MODE_FILL; ///< Current polygon fill mode.
358 bool useWireFrame = false; ///< Wireframe rendering toggle.
359 bool supportsWireFrame = false; ///< Whether the device supports wireframe.
360 std::vector<VkFramebuffer> swapChainFramebuffers; ///< Framebuffers for each swapchain image.
361
362 VkCommandPool commandPool = VK_NULL_HANDLE; ///< Command pool for graphics commands.
363 std::vector<VkCommandBuffer> commandBuffers; ///< Per-frame command buffers.
364
365 VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE; ///< Signals when a swapchain image is acquired.
366 VkSemaphore renderFinishedSemaphore = VK_NULL_HANDLE; ///< Signals when rendering is complete.
367 VkFence inFlightFence = VK_NULL_HANDLE; ///< CPU–GPU frame synchronisation fence.
368
369 VkBuffer vertexBuffer = VK_NULL_HANDLE; ///< Full-screen quad vertex buffer.
370 VkDeviceMemory vertexBufferMemory = VK_NULL_HANDLE; ///< Memory for the vertex buffer.
371 VkBuffer indexBuffer = VK_NULL_HANDLE; ///< Full-screen quad index buffer.
372 VkDeviceMemory indexBufferMemory = VK_NULL_HANDLE; ///< Memory for the index buffer.
373 uint32_t indexCount = 0; ///< Number of indices in the quad.
374
375 VkImage textureImage = VK_NULL_HANDLE; ///< Primary texture image.
376 VkDeviceMemory textureImageMemory = VK_NULL_HANDLE; ///< Memory for the primary texture.
377 VkImageView textureImageView = VK_NULL_HANDLE; ///< View into the primary texture.
378 VkImageLayout textureImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; ///< Current layout of the primary texture.
379 VkSampler textureSampler = VK_NULL_HANDLE; ///< Sampler for the primary texture.
380
381 VkDescriptorPool descriptorPool = VK_NULL_HANDLE; ///< Main descriptor pool.
382 std::vector<VkDescriptorSet> descriptorSets; ///< Per-frame descriptor sets.
383
384 VkImage depthImage = VK_NULL_HANDLE; ///< Depth/stencil image.
385 VkDeviceMemory depthImageMemory = VK_NULL_HANDLE; ///< Memory for the depth image.
386 VkImageView depthImageView = VK_NULL_HANDLE; ///< View into the depth image.
387 VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; ///< Format used for the depth buffer.
388
389 float cameraDistance = 3.0f; ///< Default camera distance from origin.
390
391 std::unique_ptr<VKText> textRenderer; ///< Text rendering subsystem.
392 VkPipeline textPipeline = VK_NULL_HANDLE; ///< Pipeline for text rendering.
393 VkPipelineLayout textPipelineLayout = VK_NULL_HANDLE; ///< Pipeline layout for text rendering.
394 VkDescriptorPool textDescriptorPool = VK_NULL_HANDLE; ///< Descriptor pool for text.
395 VkDescriptorSetLayout textDescriptorSetLayout = VK_NULL_HANDLE; ///< Descriptor layout for text.
396
397 std::vector<std::unique_ptr<VKSprite>> sprites; ///< Owned sprite instances.
398 VkPipeline spritePipeline = VK_NULL_HANDLE; ///< Pipeline for sprite rendering.
399 VkPipelineLayout spritePipelineLayout = VK_NULL_HANDLE; ///< Pipeline layout for sprites.
400 VkDescriptorPool spriteDescriptorPool = VK_NULL_HANDLE; ///< Descriptor pool for sprites.
401 VkDescriptorSetLayout spriteDescriptorSetLayout = VK_NULL_HANDLE; ///< Descriptor layout for sprites.
402 VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; ///< Vulkan debug messenger (validation layers).
403 uint32_t width, height; ///< Internal width/height tracking.
404 /** @brief Create the main descriptor set layout (UBO + sampler). */
406 /** @brief Create depth buffer image, memory, and view. */
408 /**
409 * @brief Find a supported VkFormat from the candidate list.
410 * @param candidates Ordered list of preferred formats.
411 * @param tiling Required tiling mode.
412 * @param features Required format feature flags.
413 * @return First candidate that satisfies the requirements.
414 */
415 VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
416 /** @brief Select a depth buffer format supported by the physical device. */
417 VkFormat findDepthFormat();
418 SDL_Window *window = nullptr; ///< SDL window handle.
419 SDL_Surface *surface_img = nullptr; ///< Cached SDL surface for texture uploads.
420 /** @brief Create the Vulkan instance and enable extensions/layers. */
421 void createInstance();
422 /** @brief Create the Vulkan surface from the SDL window. */
423 void createSurface();
424 /** @brief Enumerate GPUs and select the most suitable physical device. */
425 void pickPhysicalDevice();
426 /** @brief Create the logical device and retrieve queue handles. */
427 void createLogicalDevice();
428 /** @brief Allocate per-frame uniform buffers and map them persistently. */
430 /** @brief Create (or recreate) the swapchain and associated images (overridable). */
431 virtual void createSwapChain();
432 /** @brief Create image views for every swapchain image. */
433 void createImageViews();
434 /** @brief Create the main render pass with colour and depth attachments. */
435 void createRenderPass();
436 /** @brief Create framebuffers for each swapchain image view. */
437 void createFramebuffers();
438 /** @brief Create the graphics command pool. */
439 void createCommandPool();
440 /** @brief Allocate per-frame command buffers from the command pool. */
442 /** @brief Create semaphores and fences for frame synchronisation. */
443 void createSyncObjects();
444 /** @brief Destroy swapchain-dependent resources before recreation (overridable). */
445 virtual void cleanupSwapChain();
446 /**
447 * @brief Find queue families supporting graphics and presentation.
448 * @param device Physical device to query.
449 * @return Populated QueueFamilyIndices.
450 */
452 /**
453 * @brief Choose the best surface format from available options.
454 * @param availableFormats Candidate formats.
455 * @return Selected surface format.
456 */
457 VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
458 /**
459 * @brief Choose the best present mode (prefers mailbox, falls back to FIFO).
460 * @param availablePresentModes Candidate modes.
461 * @return Selected presentation mode.
462 */
463 VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
464 /**
465 * @brief Determine the swapchain image extent from surface capabilities.
466 * @param capabilities Current surface capabilities.
467 * @return Chosen extent in pixels.
468 */
469 VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
470 /**
471 * @brief Check whether a physical device meets all application requirements.
472 * @param device Candidate physical device.
473 * @return @c true if the device is suitable.
474 */
475 bool isDeviceSuitable(VkPhysicalDevice device);
476 /**
477 * @brief Query swapchain support details for a physical device.
478 * @param device Physical device to query.
479 * @return Populated SwapChainSupportDetails.
480 */
482 /**
483 * @brief Allocate a Vulkan buffer with the given usage and memory properties.
484 * @param size Buffer size in bytes.
485 * @param usage Vulkan buffer usage flags.
486 * @param properties Required memory property flags.
487 * @param buffer Output buffer handle.
488 * @param bufferMemory Output device memory handle.
489 */
490 void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory);
491 /**
492 * @brief Find a device memory type matching the filter and property flags.
493 * @param typeFilter Bit mask of acceptable memory types.
494 * @param properties Required memory property flags.
495 * @return Memory type index.
496 */
497 uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
498 /**
499 * @brief Copy data between two Vulkan buffers via a one-shot command.
500 * @param srcBuffer Source buffer.
501 * @param dstBuffer Destination buffer.
502 * @param size Number of bytes to copy.
503 */
504 void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
505 /**
506 * @brief Create a Vulkan texture image from an SDL surface.
507 * @param surfacex Source surface (RGBA).
508 */
509 void createTextureImage(SDL_Surface* surfacex);
510 /**
511 * @brief Create a Vulkan image with the specified parameters.
512 * @param width Image width in pixels.
513 * @param height Image height in pixels.
514 * @param format Pixel format.
515 * @param tiling Tiling arrangement.
516 * @param usage Image usage flags.
517 * @param properties Memory property flags.
518 * @param image Output image handle.
519 * @param imageMemory Output device memory handle.
520 */
521 void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
522 /**
523 * @brief Transition an image between two layouts using a pipeline barrier.
524 * @param image Target image.
525 * @param format Image format (used for aspect flag selection).
526 * @param oldLayout Current layout.
527 * @param newLayout Desired layout.
528 */
529 void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
530 /**
531 * @brief Copy a staging buffer into a Vulkan image.
532 * @param buffer Source buffer.
533 * @param image Destination image.
534 * @param width Image width.
535 * @param height Image height.
536 */
537 void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height);
538 /** @brief Begin a one-shot command buffer for transfer operations. */
539 VkCommandBuffer beginSingleTimeCommands();
540 /** @brief End and submit a one-shot command buffer, then wait for completion. */
541 void endSingleTimeCommands(VkCommandBuffer commandBuffer);
542 /** @brief Create the image view for the primary texture. */
544 /**
545 * @brief Create an image view with specified format and aspect flags.
546 * @param image Source image.
547 * @param format View format.
548 * @param aspectFlags Aspect mask (colour, depth, etc.).
549 * @return Created VkImageView.
550 */
551 VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags);
552 /** @brief Create the texture sampler with default filter/addressing modes. */
554 /** @brief Create the main descriptor pool. */
556 /** @brief Allocate main descriptor sets from the pool. */
558 /** @brief Write updated bindings into existing descriptor sets. */
560 /** @brief Tear down and rebuild the swapchain and all dependent resources. */
561 void recreateSwapChain();
562 /**
563 * @brief Allocate a blank texture image of the given dimensions.
564 * @param w Width in pixels.
565 * @param h Height in pixels.
566 */
567 void setupTextureImage(uint32_t w, uint32_t h);
568 /** @brief Create the descriptor set layout for text rendering. */
570 /** @brief Create the pipeline for text rendering. */
571 void createTextPipeline();
572 /** @brief Create the descriptor pool for text rendering. */
574 /** @brief Create the descriptor set layout for sprite rendering. */
576 /** @brief Create the pipeline for sprite rendering. */
578 /** @brief Create the descriptor pool for sprite rendering. */
580 };
581
582}
583
584#endif
Vulkan 2-D sprite with texture, custom shader, and instancing support.
Definition vk_sprite.hpp:55
void setupTextureImage(uint32_t w, uint32_t h)
Allocate a blank texture image of the given dimensions.
Definition vk.cpp:1075
VkCommandBuffer beginSingleTimeCommands()
Begin a one-shot command buffer for transfer operations.
Definition vk.cpp:1147
VkDescriptorPool descriptorPool
Main descriptor pool.
Definition vk.hpp:381
void createVertexBuffer()
Create and upload the vertex buffer.
Definition vk.cpp:811
void updateDescriptorSets()
Write updated bindings into existing descriptor sets.
Definition vk.cpp:1313
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
Determine the swapchain image extent from surface capabilities.
Definition vk.cpp:221
virtual bool shouldRender3D()
Control whether 3-D geometry is rendered this frame.
Definition vk.hpp:207
std::unique_ptr< VKText > textRenderer
Text rendering subsystem.
Definition vk.hpp:391
VkFormat findSupportedFormat(const std::vector< VkFormat > &candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
Find a supported VkFormat from the candidate list.
Definition vk.cpp:771
VkImage depthImage
Depth/stencil image.
Definition vk.hpp:384
float cameraDistance
Default camera distance from origin.
Definition vk.hpp:389
friend class VKAbstractModel
Definition vk.hpp:147
uint32_t indexCount
Number of indices in the quad.
Definition vk.hpp:373
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector< VkSurfaceFormatKHR > &availableFormats)
Choose the best surface format from available options.
Definition vk.cpp:199
void createDescriptorSetLayout()
Create the main descriptor set layout (UBO + sampler).
Definition vk.cpp:101
void createSurface()
Create the Vulkan surface from the SDL window.
Definition vk.cpp:365
bool controllerInputEnabled() const
Definition vk.hpp:313
VkPhysicalDevice getPhysicalDevice() const
Definition vk.hpp:323
void createTextDescriptorSetLayout()
Create the descriptor set layout for text rendering.
Definition vk.cpp:2101
VKWindow & operator=(const VKWindow &)=delete
void initWindow(const std::string &title, int width, int height, bool full=false)
Open the SDL2 window (called automatically by constructor).
Definition vk.cpp:15
VkPipelineLayout pipelineLayout
Pipeline layout for the main pass.
Definition vk.hpp:354
VkPipeline graphicsPipelineMatrix
3-D matrix-enabled graphics pipeline.
Definition vk.hpp:356
std::vector< VkBuffer > uniformBuffers
Per-frame uniform buffers.
Definition vk.hpp:349
void createSyncObjects()
Create semaphores and fences for frame synchronisation.
Definition vk.cpp:689
std::vector< VkCommandBuffer > commandBuffers
Per-frame command buffers.
Definition vk.hpp:363
std::string font
Path to the current TTF font.
Definition vk.hpp:334
std::vector< std::unique_ptr< VKSprite > > sprites
Owned sprite instances.
Definition vk.hpp:397
VkPipelineLayout textPipelineLayout
Pipeline layout for text rendering.
Definition vk.hpp:393
void createTextPipeline()
Create the pipeline for text rendering.
Definition vk.cpp:2117
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
Allocate a Vulkan buffer with the given usage and memory properties.
Definition vk.cpp:872
void recreateSwapChain()
Tear down and rebuild the swapchain and all dependent resources.
Definition vk.cpp:1798
void quit()
Post a quit event to stop the loop.
Definition vk.cpp:31
VkFormat depthFormat
Format used for the depth buffer.
Definition vk.hpp:387
virtual void cleanup()
Free all Vulkan resources (overridable).
Definition vk.cpp:1672
VkImageView textureImageView
View into the primary texture.
Definition vk.hpp:377
VkFence inFlightFence
CPU–GPU frame synchronisation fence.
Definition vk.hpp:367
uint32_t height
Internal width/height tracking.
Definition vk.hpp:403
void createCommandPool()
Create the graphics command pool.
Definition vk.cpp:663
bool getWireFrame() const
Definition vk.hpp:321
VkDescriptorSetLayout spriteDescriptorSetLayout
Descriptor layout for sprites.
Definition vk.hpp:401
bool enableControllerInput()
Enable joystick and game controller subsystems on demand.
Definition vk.cpp:43
virtual void onResize()
Called when the window is resized (optional override).
Definition vk.hpp:201
VkDeviceMemory vertexBufferMemory
Memory for the vertex buffer.
Definition vk.hpp:370
int w
Current window width.
Definition vk.hpp:219
bool useWireFrame
Wireframe rendering toggle.
Definition vk.hpp:358
VkQueue getGraphicsQueue() const
Definition vk.hpp:327
void setFont(const std::string &font, const int size=24)
Set the font used for printText().
Definition vk.cpp:35
std::vector< VkDescriptorSet > descriptorSets
Per-frame descriptor sets.
Definition vk.hpp:382
void createTextDescriptorPool()
Create the descriptor pool for text rendering.
Definition vk.cpp:2283
virtual void initVulkan()
Initialise all Vulkan objects (overridable).
Definition vk.cpp:60
VkDeviceMemory depthImageMemory
Memory for the depth image.
Definition vk.hpp:385
void createImageViews()
Create image views for every swapchain image.
Definition vk.cpp:559
void clearTextQueue()
Clear all pending text-render entries.
Definition vk.cpp:2086
VkPhysicalDevice physicalDevice
Selected GPU.
Definition vk.hpp:338
uint32_t width
Definition vk.hpp:403
void createLogicalDevice()
Create the logical device and retrieve queue handles.
Definition vk.cpp:435
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
Transition an image between two layouts using a pipeline barrier.
Definition vk.cpp:1026
VkDevice device
Logical device.
Definition vk.hpp:339
VkPipelineLayout spritePipelineLayout
Pipeline layout for sprites.
Definition vk.hpp:399
VkShaderModule createShaderModule(const std::vector< char > &code)
Compile a SPIR-V shader module.
Definition vk.cpp:162
VkBuffer vertexBuffer
Full-screen quad vertex buffer.
Definition vk.hpp:369
VkQueue graphicsQueue
Graphics submission queue.
Definition vk.hpp:340
void endSingleTimeCommands(VkCommandBuffer commandBuffer)
End and submit a one-shot command buffer, then wait for completion.
Definition vk.cpp:1166
void setFullScreen(const bool full)
Toggle fullscreen mode.
Definition vk.cpp:1781
VkDeviceMemory textureImageMemory
Memory for the primary texture.
Definition vk.hpp:376
VKSprite * createSprite(const std::string &pngPath, const std::string &vertexShader, const std::string &fragmentShaderPath="")
Create a sprite from a PNG file.
Definition vk.cpp:1840
VkImageLayout textureImageLayout
Current layout of the primary texture.
Definition vk.hpp:378
bool enableValidation
Enable Vulkan validation layers.
Definition vk.hpp:333
VkRenderPass renderPass
Main render pass.
Definition vk.hpp:353
void createDepthResources()
Create depth buffer image, memory, and view.
Definition vk.cpp:792
void createSpriteDescriptorPool()
Create the descriptor pool for sprite rendering.
Definition vk.cpp:2065
VkImage textureImage
Primary texture image.
Definition vk.hpp:375
virtual void createSwapChain()
Create (or recreate) the swapchain and associated images (overridable).
Definition vk.cpp:505
void createCommandBuffers()
Allocate per-frame command buffers from the command pool.
Definition vk.cpp:674
bool active
true while the event loop should keep running.
Definition vk.hpp:331
VkCommandPool getCommandPool() const
Definition vk.hpp:329
bool isDeviceSuitable(VkPhysicalDevice device)
Check whether a physical device meets all application requirements.
Definition vk.cpp:134
void updateTexture(SDL_Surface *newSurface)
Replace the primary texture from an SDL_Surface.
Definition vk.cpp:96
int getHeight() const
Definition vk.hpp:297
std::vector< VkDeviceMemory > uniformBuffersMemory
Memory for per-frame UBOs.
Definition vk.hpp:350
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
Copy data between two Vulkan buffers via a one-shot command.
Definition vk.cpp:904
std::vector< VkFramebuffer > swapChainFramebuffers
Framebuffers for each swapchain image.
Definition vk.hpp:360
virtual void cleanupSwapChain()
Destroy swapchain-dependent resources before recreation (overridable).
Definition vk.cpp:704
VkDescriptorSetLayout textDescriptorSetLayout
Descriptor layout for text.
Definition vk.hpp:395
void createSpritePipeline()
Create the pipeline for sprite rendering.
Definition vk.cpp:1917
void loop()
Run the blocking event/render loop.
Definition vk.cpp:234
SDL_Window * window
SDL window handle.
Definition vk.hpp:418
std::vector< void * > uniformBuffersMapped
Persistently mapped UBO pointers.
Definition vk.hpp:351
std::vector< VkImage > swapChainImages
Swapchain image handles.
Definition vk.hpp:345
void createUniformBuffers()
Allocate per-frame uniform buffers and map them persistently.
Definition vk.cpp:1333
VkPresentModeKHR chooseSwapPresentMode(const std::vector< VkPresentModeKHR > &availablePresentModes)
Choose the best present mode (prefers mailbox, falls back to FIFO).
Definition vk.cpp:212
void createFramebuffers()
Create framebuffers for each swapchain image view.
Definition vk.cpp:642
SDL_Surface * surface_img
Cached SDL surface for texture uploads.
Definition vk.hpp:419
bool supportsWireFrame
Whether the device supports wireframe.
Definition vk.hpp:359
VKWindow(VKWindow &&)=delete
VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
Create an image view with specified format and aspect flags.
Definition vk.cpp:1184
VkFormat findDepthFormat()
Select a depth buffer format supported by the physical device.
Definition vk.cpp:784
VkPolygonMode currentPolygonMode
Current polygon fill mode.
Definition vk.hpp:357
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
Copy a staging buffer into a Vulkan image.
Definition vk.cpp:1117
VkQueue presentQueue
Presentation queue.
Definition vk.hpp:341
VkDescriptorPool textDescriptorPool
Descriptor pool for text.
Definition vk.hpp:394
int h
Current window height.
Definition vk.hpp:220
void createSpriteDescriptorSetLayout()
Create the descriptor set layout for sprite rendering.
Definition vk.cpp:1901
VkSampler textureSampler
Sampler for the primary texture.
Definition vk.hpp:379
VkImageView depthImageView
View into the depth image.
Definition vk.hpp:386
VkDevice getDevice() const
Definition vk.hpp:325
virtual void proc()
Process one event/render iteration (overridable).
Definition vk.cpp:244
VkCommandPool commandPool
Command pool for graphics commands.
Definition vk.hpp:362
void createTextureSampler()
Create the texture sampler with default filter/addressing modes.
Definition vk.cpp:1207
void createRenderPass()
Create the main render pass with colour and depth attachments.
Definition vk.cpp:582
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
Find a device memory type matching the filter and property flags.
Definition vk.cpp:893
VKWindow()=default
void createTextureImage(SDL_Surface *surfacex)
Create a Vulkan texture image from an SDL surface.
Definition vk.cpp:937
virtual void event(SDL_Event &e)=0
Handle an SDL event (pure virtual).
void createTextureImageView()
Create the image view for the primary texture.
Definition vk.cpp:1180
VkSurfaceKHR surface
Window surface.
Definition vk.hpp:337
VkSemaphore imageAvailableSemaphore
Signals when a swapchain image is acquired.
Definition vk.hpp:365
void setPath(const std::string &path)
Set the asset root directory.
Definition vk.cpp:130
VKWindow & operator=(VKWindow &&)=delete
VkPipeline textPipeline
Pipeline for text rendering.
Definition vk.hpp:392
bool getTextDimensions(const std::string &text, int &width, int &height)
Measure a text string without rendering it.
Definition vk.cpp:2092
bool inputControllersInitialized
Whether joystick/controller input is enabled.
Definition vk.hpp:332
VkPipeline spritePipeline
Pipeline for sprite rendering.
Definition vk.hpp:398
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device)
Find queue families supporting graphics and presentation.
Definition vk.cpp:174
void createDescriptorPool()
Create the main descriptor pool.
Definition vk.cpp:1228
void resizeWindow(int width, int height)
Resize the SDL window and recreate the swapchain.
Definition vk.cpp:2297
VkDescriptorSetLayout descriptorSetLayout
Main descriptor set layout.
Definition vk.hpp:342
int font_size
Current font point size.
Definition vk.hpp:335
void createGraphicsPipeline()
(Re)create the graphics pipeline.
Definition vk.cpp:1351
VkSwapchainKHR swapChain
Active swapchain.
Definition vk.hpp:344
int getWidth() const
Definition vk.hpp:295
void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage &image, VkDeviceMemory &imageMemory)
Create a Vulkan image with the specified parameters.
Definition vk.cpp:995
VkDeviceMemory indexBufferMemory
Memory for the index buffer.
Definition vk.hpp:372
VkSemaphore renderFinishedSemaphore
Signals when rendering is complete.
Definition vk.hpp:366
VkPipeline graphicsPipeline
Filled-polygon graphics pipeline.
Definition vk.hpp:355
VkExtent2D swapChainExtent
Swapchain pixel dimensions.
Definition vk.hpp:347
virtual void draw()
Record rendering commands for the current frame (overridable).
Definition vk.cpp:1531
virtual ~VKWindow()
Virtual destructor — subclasses should call cleanup().
Definition vk.hpp:141
VkDescriptorPool spriteDescriptorPool
Descriptor pool for sprites.
Definition vk.hpp:400
VkInstance instance
Vulkan instance.
Definition vk.hpp:336
void setWireFrame(bool enable)
Enable or disable wireframe rendering.
Definition vk.hpp:319
std::vector< VkImageView > swapChainImageViews
Image views into swapchain images.
Definition vk.hpp:348
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device)
Query swapchain support details for a physical device.
Definition vk.cpp:371
VkBuffer indexBuffer
Full-screen quad index buffer.
Definition vk.hpp:371
VkDebugUtilsMessengerEXT debugMessenger
Vulkan debug messenger (validation layers).
Definition vk.hpp:402
void printText(const std::string &text, int x, int y, const SDL_Color &col)
Queue a text string for rendering at a screen position.
Definition vk.cpp:2080
VKWindow(const VKWindow &)=delete
mxUtil util
Asset path and utility helpers.
Definition vk.hpp:221
void createInstance()
Create the Vulkan instance and enable extensions/layers.
Definition vk.cpp:260
void pickPhysicalDevice()
Enumerate GPUs and select the most suitable physical device.
Definition vk.cpp:391
VkFormat swapChainImageFormat
Colour format of swapchain images.
Definition vk.hpp:346
void createDescriptorSets()
Allocate main descriptor sets from the pool.
Definition vk.cpp:1254
Utility bag for SDL-based applications.
Definition util.hpp:33
Exception type used throughout libmx.
Definition cfg.cpp:11
Tracks Vulkan queue family assignments needed to create a device.
Definition vk.hpp:72
std::optional< uint32_t > presentFamily
Index of the presentation queue family.
Definition vk.hpp:74
std::optional< uint32_t > graphicsFamily
Index of the graphics queue family.
Definition vk.hpp:73
bool isComplete()
Check whether both required families have been found.
Definition vk.hpp:80
Swapchain capabilities and format/mode candidates for a physical device.
Definition vk.hpp:89
std::vector< VkPresentModeKHR > presentModes
Supported presentation modes.
Definition vk.hpp:92
VkSurfaceCapabilitiesKHR capabilities
Surface capability limits.
Definition vk.hpp:90
std::vector< VkSurfaceFormatKHR > formats
Supported colour formats.
Definition vk.hpp:91
Standard UBO layout uploaded to shaders each frame.
Definition vk.hpp:102
glm::mat4 model
Model transform matrix.
Definition vk.hpp:103
glm::mat4 view
View (camera) matrix.
Definition vk.hpp:104
glm::vec4 params
Application-defined shader parameters.
Definition vk.hpp:106
glm::vec4 color
Global colour tint.
Definition vk.hpp:107
glm::mat4 proj
Projection matrix.
Definition vk.hpp:105
float pos[3]
3-D position (x, y, z).
Definition vk.hpp:63
float normal[3]
Surface normal vector.
Definition model.cpp:36
float texCoord[2]
UV texture coordinates.
Definition model.cpp:37
General SDL utility helpers, file I/O, and compression utilities.
Vulkan 2-D sprite renderer with optional custom shaders and instancing.
Vulkan SDL_ttf text renderer.