15#include <SDL_vulkan.h>
17#include <SDL_vulkan.h>
18#include<vulkan/vulkan.h>
36#include <glm/gtc/matrix_transform.hpp>
37#include <glm/gtc/type_ptr.hpp>
44#define M_PI 3.14159265358979323846
47#define VK_CHECK_RESULT(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__)); \
56 class VKAbstractModel;
138 VKWindow(
const std::string &title,
int width,
int height,
bool full =
false,
bool valid =
true);
163 void setFont(
const std::string &
font,
const int size = 24);
175 void setPath(
const std::string &path);
190 virtual void event(SDL_Event &e) = 0;
252 void printText(
const std::string &text,
int x,
int y,
const SDL_Color &col);
273 VKSprite*
createSprite(
const std::string &pngPath,
const std::string &vertexShader,
const std::string &fragmentShaderPath =
"");
397 std::vector<std::unique_ptr<VKSprite>>
sprites;
415 VkFormat
findSupportedFormat(
const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
490 void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory);
497 uint32_t
findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
504 void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
521 void createImage(uint32_t
width, uint32_t
height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
529 void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
551 VkImageView
createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags);
Vulkan 2-D sprite with texture, custom shader, and instancing support.
void setupTextureImage(uint32_t w, uint32_t h)
Allocate a blank texture image of the given dimensions.
VkCommandBuffer beginSingleTimeCommands()
Begin a one-shot command buffer for transfer operations.
VkDescriptorPool descriptorPool
Main descriptor pool.
void createVertexBuffer()
Create and upload the vertex buffer.
void updateDescriptorSets()
Write updated bindings into existing descriptor sets.
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
Determine the swapchain image extent from surface capabilities.
virtual bool shouldRender3D()
Control whether 3-D geometry is rendered this frame.
std::unique_ptr< VKText > textRenderer
Text rendering subsystem.
VkFormat findSupportedFormat(const std::vector< VkFormat > &candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
Find a supported VkFormat from the candidate list.
VkImage depthImage
Depth/stencil image.
float cameraDistance
Default camera distance from origin.
friend class VKAbstractModel
uint32_t indexCount
Number of indices in the quad.
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector< VkSurfaceFormatKHR > &availableFormats)
Choose the best surface format from available options.
void createDescriptorSetLayout()
Create the main descriptor set layout (UBO + sampler).
void createSurface()
Create the Vulkan surface from the SDL window.
bool controllerInputEnabled() const
VkPhysicalDevice getPhysicalDevice() const
void createTextDescriptorSetLayout()
Create the descriptor set layout for text rendering.
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).
VkPipelineLayout pipelineLayout
Pipeline layout for the main pass.
VkPipeline graphicsPipelineMatrix
3-D matrix-enabled graphics pipeline.
std::vector< VkBuffer > uniformBuffers
Per-frame uniform buffers.
void createSyncObjects()
Create semaphores and fences for frame synchronisation.
std::vector< VkCommandBuffer > commandBuffers
Per-frame command buffers.
std::string font
Path to the current TTF font.
std::vector< std::unique_ptr< VKSprite > > sprites
Owned sprite instances.
VkPipelineLayout textPipelineLayout
Pipeline layout for text rendering.
void createTextPipeline()
Create the pipeline for text rendering.
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
Allocate a Vulkan buffer with the given usage and memory properties.
void recreateSwapChain()
Tear down and rebuild the swapchain and all dependent resources.
void quit()
Post a quit event to stop the loop.
VkFormat depthFormat
Format used for the depth buffer.
virtual void cleanup()
Free all Vulkan resources (overridable).
VkImageView textureImageView
View into the primary texture.
VkFence inFlightFence
CPU–GPU frame synchronisation fence.
uint32_t height
Internal width/height tracking.
void createCommandPool()
Create the graphics command pool.
bool getWireFrame() const
VkDescriptorSetLayout spriteDescriptorSetLayout
Descriptor layout for sprites.
bool enableControllerInput()
Enable joystick and game controller subsystems on demand.
virtual void onResize()
Called when the window is resized (optional override).
VkDeviceMemory vertexBufferMemory
Memory for the vertex buffer.
int w
Current window width.
bool useWireFrame
Wireframe rendering toggle.
VkQueue getGraphicsQueue() const
void setFont(const std::string &font, const int size=24)
Set the font used for printText().
std::vector< VkDescriptorSet > descriptorSets
Per-frame descriptor sets.
void createTextDescriptorPool()
Create the descriptor pool for text rendering.
virtual void initVulkan()
Initialise all Vulkan objects (overridable).
VkDeviceMemory depthImageMemory
Memory for the depth image.
void createImageViews()
Create image views for every swapchain image.
void clearTextQueue()
Clear all pending text-render entries.
VkPhysicalDevice physicalDevice
Selected GPU.
void createLogicalDevice()
Create the logical device and retrieve queue handles.
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
Transition an image between two layouts using a pipeline barrier.
VkDevice device
Logical device.
VkPipelineLayout spritePipelineLayout
Pipeline layout for sprites.
VkShaderModule createShaderModule(const std::vector< char > &code)
Compile a SPIR-V shader module.
VkBuffer vertexBuffer
Full-screen quad vertex buffer.
VkQueue graphicsQueue
Graphics submission queue.
void endSingleTimeCommands(VkCommandBuffer commandBuffer)
End and submit a one-shot command buffer, then wait for completion.
void setFullScreen(const bool full)
Toggle fullscreen mode.
VkDeviceMemory textureImageMemory
Memory for the primary texture.
VKSprite * createSprite(const std::string &pngPath, const std::string &vertexShader, const std::string &fragmentShaderPath="")
Create a sprite from a PNG file.
VkImageLayout textureImageLayout
Current layout of the primary texture.
bool enableValidation
Enable Vulkan validation layers.
VkRenderPass renderPass
Main render pass.
void createDepthResources()
Create depth buffer image, memory, and view.
void createSpriteDescriptorPool()
Create the descriptor pool for sprite rendering.
VkImage textureImage
Primary texture image.
virtual void createSwapChain()
Create (or recreate) the swapchain and associated images (overridable).
void createCommandBuffers()
Allocate per-frame command buffers from the command pool.
bool active
true while the event loop should keep running.
VkCommandPool getCommandPool() const
bool isDeviceSuitable(VkPhysicalDevice device)
Check whether a physical device meets all application requirements.
void updateTexture(SDL_Surface *newSurface)
Replace the primary texture from an SDL_Surface.
std::vector< VkDeviceMemory > uniformBuffersMemory
Memory for per-frame UBOs.
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
Copy data between two Vulkan buffers via a one-shot command.
std::vector< VkFramebuffer > swapChainFramebuffers
Framebuffers for each swapchain image.
virtual void cleanupSwapChain()
Destroy swapchain-dependent resources before recreation (overridable).
VkDescriptorSetLayout textDescriptorSetLayout
Descriptor layout for text.
void createSpritePipeline()
Create the pipeline for sprite rendering.
void loop()
Run the blocking event/render loop.
SDL_Window * window
SDL window handle.
std::vector< void * > uniformBuffersMapped
Persistently mapped UBO pointers.
std::vector< VkImage > swapChainImages
Swapchain image handles.
void createUniformBuffers()
Allocate per-frame uniform buffers and map them persistently.
VkPresentModeKHR chooseSwapPresentMode(const std::vector< VkPresentModeKHR > &availablePresentModes)
Choose the best present mode (prefers mailbox, falls back to FIFO).
void createFramebuffers()
Create framebuffers for each swapchain image view.
SDL_Surface * surface_img
Cached SDL surface for texture uploads.
bool supportsWireFrame
Whether the device supports wireframe.
VKWindow(VKWindow &&)=delete
VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
Create an image view with specified format and aspect flags.
VkFormat findDepthFormat()
Select a depth buffer format supported by the physical device.
VkPolygonMode currentPolygonMode
Current polygon fill mode.
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
Copy a staging buffer into a Vulkan image.
VkQueue presentQueue
Presentation queue.
VkDescriptorPool textDescriptorPool
Descriptor pool for text.
int h
Current window height.
void createSpriteDescriptorSetLayout()
Create the descriptor set layout for sprite rendering.
VkSampler textureSampler
Sampler for the primary texture.
VkImageView depthImageView
View into the depth image.
VkDevice getDevice() const
virtual void proc()
Process one event/render iteration (overridable).
VkCommandPool commandPool
Command pool for graphics commands.
void createTextureSampler()
Create the texture sampler with default filter/addressing modes.
void createRenderPass()
Create the main render pass with colour and depth attachments.
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
Find a device memory type matching the filter and property flags.
void createTextureImage(SDL_Surface *surfacex)
Create a Vulkan texture image from an SDL surface.
virtual void event(SDL_Event &e)=0
Handle an SDL event (pure virtual).
void createTextureImageView()
Create the image view for the primary texture.
VkSurfaceKHR surface
Window surface.
VkSemaphore imageAvailableSemaphore
Signals when a swapchain image is acquired.
void setPath(const std::string &path)
Set the asset root directory.
VKWindow & operator=(VKWindow &&)=delete
VkPipeline textPipeline
Pipeline for text rendering.
bool getTextDimensions(const std::string &text, int &width, int &height)
Measure a text string without rendering it.
bool inputControllersInitialized
Whether joystick/controller input is enabled.
VkPipeline spritePipeline
Pipeline for sprite rendering.
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device)
Find queue families supporting graphics and presentation.
void createDescriptorPool()
Create the main descriptor pool.
void resizeWindow(int width, int height)
Resize the SDL window and recreate the swapchain.
VkDescriptorSetLayout descriptorSetLayout
Main descriptor set layout.
int font_size
Current font point size.
void createGraphicsPipeline()
(Re)create the graphics pipeline.
VkSwapchainKHR swapChain
Active swapchain.
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.
VkDeviceMemory indexBufferMemory
Memory for the index buffer.
VkSemaphore renderFinishedSemaphore
Signals when rendering is complete.
VkPipeline graphicsPipeline
Filled-polygon graphics pipeline.
VkExtent2D swapChainExtent
Swapchain pixel dimensions.
virtual void draw()
Record rendering commands for the current frame (overridable).
virtual ~VKWindow()
Virtual destructor — subclasses should call cleanup().
VkDescriptorPool spriteDescriptorPool
Descriptor pool for sprites.
VkInstance instance
Vulkan instance.
void setWireFrame(bool enable)
Enable or disable wireframe rendering.
std::vector< VkImageView > swapChainImageViews
Image views into swapchain images.
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device)
Query swapchain support details for a physical device.
VkBuffer indexBuffer
Full-screen quad index buffer.
VkDebugUtilsMessengerEXT debugMessenger
Vulkan debug messenger (validation layers).
void printText(const std::string &text, int x, int y, const SDL_Color &col)
Queue a text string for rendering at a screen position.
VKWindow(const VKWindow &)=delete
mxUtil util
Asset path and utility helpers.
void createInstance()
Create the Vulkan instance and enable extensions/layers.
void pickPhysicalDevice()
Enumerate GPUs and select the most suitable physical device.
VkFormat swapChainImageFormat
Colour format of swapchain images.
void createDescriptorSets()
Allocate main descriptor sets from the pool.
Utility bag for SDL-based applications.
Exception type used throughout libmx.
Tracks Vulkan queue family assignments needed to create a device.
std::optional< uint32_t > presentFamily
Index of the presentation queue family.
std::optional< uint32_t > graphicsFamily
Index of the graphics queue family.
bool isComplete()
Check whether both required families have been found.
Swapchain capabilities and format/mode candidates for a physical device.
std::vector< VkPresentModeKHR > presentModes
Supported presentation modes.
VkSurfaceCapabilitiesKHR capabilities
Surface capability limits.
std::vector< VkSurfaceFormatKHR > formats
Supported colour formats.
float pos[3]
3-D position (x, y, z).
float normal[3]
Surface normal vector.
float texCoord[2]
UV texture coordinates.
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.