Mandrill 2025.6.0
Loading...
Searching...
No Matches
Helpers.h
1#pragma once
2
3#include "Common.h"
4
5#include "Buffer.h"
6#include "Device.h"
7#include "Error.h"
8#include "Image.h"
9#include "Log.h"
10
11namespace Mandrill
12{
16 class MANDRILL_API Helpers
17 {
18 public:
24 inline static VkCommandBuffer cmdBegin(ptr<Device> pDevice)
25 {
26 VkCommandBufferAllocateInfo ai = {
27 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
28 .commandPool = pDevice->getCommandPool(),
29 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
30 .commandBufferCount = 1,
31 };
32
33 VkCommandBuffer cmd;
34 Check::Vk(vkAllocateCommandBuffers(pDevice->getDevice(), &ai, &cmd));
35
36 VkCommandBufferBeginInfo bi = {
37 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
38 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
39 };
40
41 Check::Vk(vkBeginCommandBuffer(cmd, &bi));
42
43 return cmd;
44 }
45
51 inline static void cmdEnd(ptr<Device> pDevice, VkCommandBuffer cmd,
52 const std::vector<VkSemaphore>& waitSemaphores = {},
53 const std::vector<VkPipelineStageFlags>& waitStages = {},
54 const std::vector<VkSemaphore>& signalSemaphores = {})
55 {
56 Check::Vk(vkEndCommandBuffer(cmd));
57
58 VkSubmitInfo si = {
59 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
60 .waitSemaphoreCount = count(waitSemaphores),
61 .pWaitSemaphores = waitSemaphores.data(),
62 .pWaitDstStageMask = waitStages.data(),
63 .commandBufferCount = 1,
64 .pCommandBuffers = &cmd,
65 .signalSemaphoreCount = count(signalSemaphores),
66 .pSignalSemaphores = signalSemaphores.data(),
67 };
68
69 Check::Vk(vkQueueSubmit(pDevice->getQueue(), 1, &si, nullptr));
70 Check::Vk(vkQueueWaitIdle(pDevice->getQueue()));
71
72 vkFreeCommandBuffers(pDevice->getDevice(), pDevice->getCommandPool(), 1, &cmd);
73 }
74
82 inline static uint32_t findMemoryType(ptr<Device> pDevice, uint32_t typeFilter,
83 VkMemoryPropertyFlags properties)
84 {
85 for (uint32_t i = 0; i < pDevice->getProperties().memory.memoryTypeCount; i++) {
86 if ((typeFilter & (1 << i)) &&
87 (pDevice->getProperties().memory.memoryTypes[i].propertyFlags & properties) == properties) {
88 return i;
89 }
90 }
91
92 Log::Error("Failed to find suitable memory type");
93 return UINT32_MAX;
94 }
95
104 inline static VkFormat findSupportedFormat(ptr<Device> pDevice, std::vector<VkFormat> candidates,
105 VkImageTiling tiling, VkFormatFeatureFlags features)
106 {
107 for (auto& c : candidates) {
108 VkFormatProperties properties;
109 vkGetPhysicalDeviceFormatProperties(pDevice->getPhysicalDevice(), c, &properties);
110
111 if (tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features) {
112 return c;
113 } else if (tiling == VK_IMAGE_TILING_OPTIMAL &&
114 (properties.optimalTilingFeatures & features) == features) {
115 return c;
116 }
117 }
118 return VK_FORMAT_UNDEFINED;
119 }
120
126 inline static VkFormat findDepthFormat(ptr<Device> pDevice)
127 {
128 std::vector<VkFormat> candidates;
129 candidates.push_back(VK_FORMAT_D32_SFLOAT);
130 candidates.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
131 candidates.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
132
133 return findSupportedFormat(pDevice, candidates, VK_IMAGE_TILING_OPTIMAL,
134 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
135 }
136
149 inline static void imageBarrier(VkCommandBuffer cmd, VkImage image, VkPipelineStageFlags2 srcStage,
150 VkAccessFlags2 srcAccess, VkPipelineStageFlags2 dstStage,
151 VkAccessFlags2 dstAccess, VkImageLayout oldLayout, VkImageLayout newLayout,
152 VkImageSubresourceRange* pSubresourceRange = nullptr)
153 {
154 VkImageSubresourceRange defaultSubresourceRange = {
155 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
156 .baseMipLevel = 0,
157 .levelCount = 1,
158 .baseArrayLayer = 0,
159 .layerCount = 1,
160 };
161
162 VkImageMemoryBarrier2 barrier = {
163 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
164 .srcStageMask = srcStage,
165 .srcAccessMask = srcAccess,
166 .dstStageMask = dstStage,
167 .dstAccessMask = dstAccess,
168 .oldLayout = oldLayout,
169 .newLayout = newLayout,
170 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
171 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
172 .image = image,
173 .subresourceRange = pSubresourceRange ? *pSubresourceRange : defaultSubresourceRange,
174 };
175
176 VkDependencyInfo dependencyInfo = {
177 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
178 .imageMemoryBarrierCount = 1,
179 .pImageMemoryBarriers = &barrier,
180 };
181
182 vkCmdPipelineBarrier2(cmd, &dependencyInfo);
183 }
184
194 inline static void copyBufferToImage(VkCommandBuffer cmd, VkBuffer buffer, VkImage image, uint32_t width,
195 uint32_t height, uint32_t depth)
196 {
197 VkBufferImageCopy region = {
198 .bufferOffset = 0,
199 .bufferRowLength = 0,
200 .bufferImageHeight = 0,
201 .imageSubresource =
202 {
203 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
204 .mipLevel = 0,
205 .baseArrayLayer = 0,
206 .layerCount = 1,
207 },
208 .imageOffset = {0, 0},
209 .imageExtent = {width, height, depth},
210 };
211
212 vkCmdCopyBufferToImage(cmd, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
213 }
214
224 inline static void copyImageToBuffer(VkCommandBuffer cmd, VkImage image, VkBuffer buffer, uint32_t width,
225 uint32_t height, uint32_t depth)
226 {
227 VkBufferImageCopy region = {
228 .bufferOffset = 0,
229 .bufferRowLength = 0,
230 .bufferImageHeight = 0,
231 .imageSubresource =
232 {
233 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
234 .mipLevel = 0,
235 .baseArrayLayer = 0,
236 .layerCount = 1,
237 },
238 .imageOffset = {0, 0},
239 .imageExtent = {width, height, depth},
240 };
241
242 vkCmdCopyImageToBuffer(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1, &region);
243 }
244
251 inline static VkDeviceSize alignTo(VkDeviceSize value, VkDeviceSize alignment)
252 {
253 return (value + alignment - 1) & ~(alignment - 1);
254 }
255
261 inline static float random(bool reset = false)
262 {
263 static std::random_device dev;
264 static std::mt19937 rng(dev());
265 static std::uniform_real_distribution<float> dis(0.0f, 1.0f);
266 if (reset) {
267 rng.seed();
268 }
269 return dis(rng);
270 }
271 };
272} // namespace Mandrill
Class with Vulkan helper functions. This class provides static functions that can be called directly ...
Definition Helpers.h:17
static VkDeviceSize alignTo(VkDeviceSize value, VkDeviceSize alignment)
Aligne a value to a given alignment.
Definition Helpers.h:251
static VkFormat findSupportedFormat(ptr< Device > pDevice, std::vector< VkFormat > candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
Find supported format for an attachment.
Definition Helpers.h:104
static void copyBufferToImage(VkCommandBuffer cmd, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t depth)
Copy a buffer to an image.
Definition Helpers.h:194
static void imageBarrier(VkCommandBuffer cmd, VkImage image, VkPipelineStageFlags2 srcStage, VkAccessFlags2 srcAccess, VkPipelineStageFlags2 dstStage, VkAccessFlags2 dstAccess, VkImageLayout oldLayout, VkImageLayout newLayout, VkImageSubresourceRange *pSubresourceRange=nullptr)
Create an image barrier with layout transition.
Definition Helpers.h:149
static VkFormat findDepthFormat(ptr< Device > pDevice)
Find a supported depth format for a depth attachment.
Definition Helpers.h:126
static void cmdEnd(ptr< Device > pDevice, VkCommandBuffer cmd, const std::vector< VkSemaphore > &waitSemaphores={}, const std::vector< VkPipelineStageFlags > &waitStages={}, const std::vector< VkSemaphore > &signalSemaphores={})
End a one-time use command buffer that was initialized with a call to cmdBegin().
Definition Helpers.h:51
static void copyImageToBuffer(VkCommandBuffer cmd, VkImage image, VkBuffer buffer, uint32_t width, uint32_t height, uint32_t depth)
Copy an image to a buffer.
Definition Helpers.h:224
static VkCommandBuffer cmdBegin(ptr< Device > pDevice)
Create a new one-time use command buffer. This call should be paired with a corresponding call to cmd...
Definition Helpers.h:24
static float random(bool reset=false)
Return a random value from the interval [0.0, 1.0)
Definition Helpers.h:261
static uint32_t findMemoryType(ptr< Device > pDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties)
Find a suitable memory type given the memory properties.
Definition Helpers.h:82