MXVK Vulkan Framework 0.33.1
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk_stencil.hpp
Go to the documentation of this file.
1/**
2 * @file mxvk_stencil.hpp
3 * @brief Reusable dynamic-rendering stencil image and fullscreen stencil pipelines.
4 */
5#pragma once
6
7#include "mxvk_context.hpp"
8#include "mxvk_resource.hpp"
9
10#include <volk/volk.h>
11
12#include <cstdint>
13#include <string>
14
15namespace mxvk {
16
17 /**
18 * @brief Owns a stencil attachment and two fullscreen pipelines for stencil-masked rendering.
19 *
20 * VK_Stencil is intended for use from VK_Window subclasses. Call initialize() once the
21 * window has a valid device and swapchain extent, call prepare_for_rendering() before
22 * VK_Window begins dynamic rendering, pass configure_attachment() through
23 * VK_Window::onConfigureDepthStencilAttachments(), then call draw_mask() before draw_content()
24 * inside VK_Window::onRecordCustomRendering().
25 */
26 class VK_Stencil {
27 public:
28 /**
29 * @brief Push-constant payload shared by the mask and content shaders.
30 *
31 * The helper does not assign semantic meaning beyond the field names; examples use
32 * the values for animation time, aspect-ratio correction, phase offsets, and scale.
33 */
35 /** @brief Elapsed animation time in seconds. */
36 float time = 0.0f;
37 /** @brief Render target width divided by height. */
38 float aspect = 1.0f;
39 /** @brief User-defined phase value for animated stencil/content shaders. */
40 float phase = 0.0f;
41 /** @brief User-defined scale value for stencil/content shaders. */
42 float scale = 1.0f;
43 };
44
45 /** @brief Construct an empty stencil helper. */
46 VK_Stencil() = default;
47
48 /** @brief Destroy any live Vulkan resources owned by the helper. */
50
51 VK_Stencil(const VK_Stencil &) = delete;
52 VK_Stencil(VK_Stencil &&) = delete;
53 VK_Stencil &operator=(const VK_Stencil &) = delete;
55
56 /**
57 * @brief Create the stencil attachment and fullscreen mask/content pipelines.
58 * @param context Vulkan device, physical device, queue, and command pool handles.
59 * @param extent Size of the stencil attachment in pixels.
60 * @param color_format Color attachment format used by the active dynamic rendering pass.
61 * @param depth_format Depth attachment format used by the active dynamic rendering pass.
62 * @param pipeline_cache Optional pipeline cache used when creating graphics pipelines.
63 * @param mask_vertex_shader SPIR-V vertex shader path for the stencil-writing pass.
64 * @param mask_fragment_shader SPIR-V fragment shader path for the stencil-writing pass.
65 * @param content_vertex_shader SPIR-V vertex shader path for the stencil-tested content pass.
66 * @param content_fragment_shader SPIR-V fragment shader path for the stencil-tested content pass.
67 *
68 * Existing resources are destroyed before the new resources are created.
69 */
70 void initialize(const VulkanContext &context,
71 VkExtent2D extent,
72 VkFormat color_format,
73 VkFormat depth_format,
74 VkPipelineCache pipeline_cache,
75 const std::string &mask_vertex_shader,
76 const std::string &mask_fragment_shader,
77 const std::string &content_vertex_shader,
78 const std::string &content_fragment_shader);
79
80 /** @brief Release all Vulkan resources and reset the helper to an empty state. */
81 void destroy();
82
83 /**
84 * @brief Recreate the stencil image for a new render extent.
85 * @param extent New attachment size in pixels.
86 *
87 * Pipelines are retained because they depend on formats, not image dimensions.
88 */
89 void resize(VkExtent2D extent);
90
91 /**
92 * @brief Transition the stencil image for use as a dynamic-rendering stencil attachment.
93 * @param cmd Command buffer currently recording outside a rendering scope.
94 */
95 void prepare_for_rendering(VkCommandBuffer cmd);
96
97 /**
98 * @brief Fill a VkRenderingAttachmentInfo for VK_Window dynamic rendering.
99 * @param attachment Attachment info to populate when the helper is valid.
100 */
101 void configure_attachment(VkRenderingAttachmentInfo &attachment) const;
102
103 /**
104 * @brief Draw the fullscreen stencil-writing mask pass.
105 * @param cmd Command buffer recording inside the dynamic-rendering scope.
106 * @param push_constants Values passed to the mask fragment shader.
107 */
108 void draw_mask(VkCommandBuffer cmd, const PushConstants &push_constants) const;
109
110 /**
111 * @brief Draw the fullscreen content pass clipped by stencil reference value 1.
112 * @param cmd Command buffer recording inside the dynamic-rendering scope.
113 * @param push_constants Values passed to the content fragment shader.
114 */
115 void draw_content(VkCommandBuffer cmd, const PushConstants &push_constants) const;
116
117 /** @brief Return the selected stencil-capable image format. */
118 [[nodiscard]] VkFormat stencil_format() const noexcept { return stencil_image_format; }
119
120 /** @brief Return the current stencil attachment extent. */
121 [[nodiscard]] VkExtent2D extent() const noexcept { return stencil_extent; }
122
123 /** @brief Check whether image resources are ready for rendering. */
124 [[nodiscard]] bool valid() const noexcept;
125
126 private:
127 /** @brief Allocate the stencil image, memory, and image view. */
128 void create_resources();
129
130 /** @brief Create pipeline layouts and mask/content graphics pipelines. */
131 void create_pipelines();
132
133 /** @brief Destroy mask/content graphics pipelines and pipeline layouts. */
134 void destroy_pipelines();
135
136 /** @brief Destroy stencil image resources. */
137 void destroy_image();
138
139 /** @brief Select the first supported format that can be used as a stencil attachment. */
140 [[nodiscard]] VkFormat choose_stencil_format() const;
141
142 /**
143 * @brief Create one fullscreen graphics pipeline.
144 * @param vertex_shader SPIR-V vertex shader path.
145 * @param fragment_shader SPIR-V fragment shader path.
146 * @param layout Pipeline layout with the PushConstants range.
147 * @param writes_stencil True for the mask pass, false for the stencil-tested content pass.
148 * @return Created Vulkan graphics pipeline.
149 */
150 [[nodiscard]] VkPipeline create_pipeline(const std::string &vertex_shader,
151 const std::string &fragment_shader,
152 VkPipelineLayout layout,
153 bool writes_stencil) const;
154
155 VulkanContext vk_context{};
156 VkExtent2D stencil_extent{};
157 VkFormat render_color_format = VK_FORMAT_UNDEFINED;
158 VkFormat render_depth_format = VK_FORMAT_UNDEFINED;
159 VkFormat stencil_image_format = VK_FORMAT_UNDEFINED;
160 VkPipelineCache cache = VK_NULL_HANDLE;
161 std::string mask_vertex_path{};
162 std::string mask_fragment_path{};
163 std::string content_vertex_path{};
164 std::string content_fragment_path{};
165
166 VkImage image = VK_NULL_HANDLE;
167 VkDeviceMemory memory = VK_NULL_HANDLE;
168 VkImageView view = VK_NULL_HANDLE;
169 bool image_initialized = false;
170
171 VkPipelineLayout mask_layout = VK_NULL_HANDLE;
172 VkPipelineLayout content_layout = VK_NULL_HANDLE;
173 VkPipeline mask_pipeline = VK_NULL_HANDLE;
174 VkPipeline content_pipeline = VK_NULL_HANDLE;
175 };
176
177} // namespace mxvk
VK_Stencil(VK_Stencil &&)=delete
void initialize(const VulkanContext &context, VkExtent2D extent, VkFormat color_format, VkFormat depth_format, VkPipelineCache pipeline_cache, const std::string &mask_vertex_shader, const std::string &mask_fragment_shader, const std::string &content_vertex_shader, const std::string &content_fragment_shader)
Create the stencil attachment and fullscreen mask/content pipelines.
VK_Stencil(const VK_Stencil &)=delete
void draw_mask(VkCommandBuffer cmd, const PushConstants &push_constants) const
Draw the fullscreen stencil-writing mask pass.
VkExtent2D extent() const noexcept
Return the current stencil attachment extent.
void draw_content(VkCommandBuffer cmd, const PushConstants &push_constants) const
Draw the fullscreen content pass clipped by stencil reference value 1.
VK_Stencil()=default
Construct an empty stencil helper.
void prepare_for_rendering(VkCommandBuffer cmd)
Transition the stencil image for use as a dynamic-rendering stencil attachment.
VK_Stencil & operator=(VK_Stencil &&)=delete
void destroy()
Release all Vulkan resources and reset the helper to an empty state.
VkFormat stencil_format() const noexcept
Return the selected stencil-capable image format.
VK_Stencil & operator=(const VK_Stencil &)=delete
void resize(VkExtent2D extent)
Recreate the stencil image for a new render extent.
void configure_attachment(VkRenderingAttachmentInfo &attachment) const
Fill a VkRenderingAttachmentInfo for VK_Window dynamic rendering.
bool valid() const noexcept
Check whether image resources are ready for rendering.
Minimal Vulkan handles shared across MXVK helpers.
Reusable Vulkan buffer, image, upload, and one-shot command helpers.
Utilities for loading and saving PNG images.
Definition mxvk.hpp:31
Push-constant payload shared by the mask and content shaders.
float time
Elapsed animation time in seconds.
float phase
User-defined phase value for animated stencil/content shaders.
float aspect
Render target width divided by height.
float scale
User-defined scale value for stencil/content shaders.
Minimal Vulkan handles required by MXVK resource helpers.