MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
surface.cpp
Go to the documentation of this file.
1#include "mxvk/argz.hpp"
2#include "mxvk/mxvk.hpp"
4#include <SDL3/SDL.h>
5#include <cstdint>
6#include <format>
7#include <iostream>
8#include <memory>
9#include <random>
10
11namespace surface {
12
13 struct SurfaceDeleter {
14 void operator()(SDL_Surface *surface) const {
15 if (surface != nullptr) {
16 SDL_DestroySurface(surface);
17 }
18 }
19 };
20
21 class SurfaceWindow : public mxvk::VK_Window {
22
23 public:
24 SurfaceWindow(std::string shader_path, int width, int height, bool full, bool enable_vsync) : mxvk::VK_Window(" -[ MXVK Skeleton ] - ", width, height, full, MXVK_VALIDATION, enable_vsync) {
25 std::cout << "surface: started example.\n";
26 if (!resize_canvas_to_swapchain()) {
27 throw mxvk::Exception("surface: failed to initialize canvas from swapchain extent");
28 }
29 surf = createSprite(bg.get(), "", shader_path);
30 }
31 void event(SDL_Event &e) override {
32 switch (e.type) {
33 case SDL_EVENT_KEY_DOWN:
34 if (e.key.key == SDLK_ESCAPE) {
35 exit();
36 return;
37 }
38 break;
39 case SDL_EVENT_QUIT:
40 exit();
41 return;
42 }
43 }
44 void proc() override {
45 SDL_Surface *canvas = bg.get();
46 if (canvas == nullptr || !SDL_LockSurface(canvas)) {
47 return;
48 }
49 auto *pixels = static_cast<Uint8 *>(canvas->pixels);
50 for (int y = 0; y < canvas->h; ++y) {
51 Uint8 *row = pixels + y * canvas->pitch;
52 for (int x = 0; x < canvas->w; ++x) {
53 const std::uint32_t color = random_color(random_engine);
54 Uint8 *p = row + x * 4;
55 p[0] = static_cast<Uint8>(color & 0xFFU);
56 p[1] = static_cast<Uint8>((color >> 8U) & 0xFFU);
57 p[2] = static_cast<Uint8>((color >> 16U) & 0xFFU);
58 p[3] = static_cast<Uint8>(255);
59 }
60 }
61 SDL_UnlockSurface(canvas);
62 surf->updateTexture(canvas);
63 surf->drawSpriteRect(0, 0, target_width, target_height);
64 }
65
66 void onSwapchainRecreated() override {
67 resize_canvas_to_swapchain();
68 }
69
70 private:
71 bool resize_canvas_to_swapchain() {
72 if (!ensureRenderResources()) {
73 return false;
74 }
75 const VkExtent2D extent = getSwapchainExtent();
76 if (extent.width == 0U || extent.height == 0U) {
77 return false;
78 }
79 resize_canvas(static_cast<int>(extent.width), static_cast<int>(extent.height));
80 return true;
81 }
82
83 void resize_canvas(int width, int height) {
84 if (width <= 0 || height <= 0 || (bg != nullptr && bg->w == width && bg->h == height)) {
85 return;
86 }
87 bg.reset(SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32));
88 if (bg == nullptr) {
89 throw mxvk::Exception("Failed to create surface canvas: " + std::string(SDL_GetError()));
90 }
91 SDL_FillSurfaceRect(bg.get(), nullptr, SDL_MapSurfaceRGBA(bg.get(), 0, 0, 0, 255));
92 target_width = width;
93 target_height = height;
94 }
95
96 mxvk::VK_Sprite *surf = nullptr;
97 std::unique_ptr<SDL_Surface, surface::SurfaceDeleter> bg;
98 int target_width = 1280;
99 int target_height = 720;
100 std::mt19937 random_engine{std::random_device{}()};
101 std::uniform_int_distribution<std::uint32_t> random_color{0U, 0x00FFFFFFU};
102 };
103} // namespace surface
104
105int main(int argc, char **argv) {
106 try {
107 Arguments args = proc_args(argc, argv);
108 surface::SurfaceWindow window(args.filename, args.width, args.height, args.fullscreen, args.enable_vsync);
109 window.loop();
110 } catch (mxvk::Exception &e) {
111 std::cerr << std::format("mxvk: Exception: {}\n", e.text());
112 return EXIT_FAILURE;
113 } catch (ArgException<std::string> &e) {
114 std::cerr << std::format("mxvk: Argument Exception: {}\n", e.text());
115 return EXIT_FAILURE;
116 }
117 return EXIT_SUCCESS;
118}
Lightweight, header-only, template command-line argument parser.
Arguments proc_args(int &argc, char **argv)
Parse standard libmx2 command-line options from main()'s argv.
Definition argz.hpp:872
Exception thrown by Argz::proc() on unrecognised or malformed options.
Definition argz.hpp:178
std::string text() const
Main Vulkan window wrapper for MXVK.
Definition mxvk.hpp:37
VkExtent2D getSwapchainExtent() const noexcept
Get the current swapchain extent.
Definition mxvk.hpp:186
void loop()
Run the main event/render loop.
Definition mxvk.cpp:600
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
void exit()
Request loop termination.
Definition mxvk.cpp:1126
bool ensureRenderResources()
Ensure deferred render resources are initialized.
Definition mxvk.cpp:1406
VK_Window()=default
Construct an empty window object.
void onSwapchainRecreated() override
Called after swapchain and render resources are recreated.
Definition surface.cpp:66
SurfaceWindow(std::string shader_path, int width, int height, bool full, bool enable_vsync)
Definition surface.cpp:24
void proc() override
Execute one processing/update step.
Definition surface.cpp:44
void event(SDL_Event &e) override
Handle one SDL event.
Definition surface.cpp:31
int main(void)
Definition main.cpp:7
#define MXVK_VALIDATION
Definition mxvk.hpp:27
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30
Plain data structure returned by proc_args() with all common libmx2 CLI options.
Definition argz.hpp:730
bool fullscreen
Whether fullscreen mode was requested.
Definition argz.hpp:736
bool enable_vsync
Enable FIFO present mode / v-sync (--enable-vsync).
Definition argz.hpp:750
int height
Viewport height in pixels (default: 720).
Definition argz.hpp:733
std::string filename
Optional input filename (--filename).
Definition argz.hpp:738
int width
Viewport width in pixels (default: 1280).
Definition argz.hpp:732
void operator()(SDL_Surface *surface) const
Definition surface.cpp:14