2#include <backends/imgui_impl_vulkan.h>
13 VkPhysicalDevice physicalDevice,
14 VkCommandPool commandPool,
15 VkQueue graphicsQueue)
17 m_physicalDevice(physicalDevice),
18 m_commandPool(commandPool),
19 m_graphicsQueue(graphicsQueue) {}
27 if (!data ||
width == 0 ||
height == 0)
return false;
35 VkDeviceSize imageSize =
static_cast<VkDeviceSize
>(
width) *
height * 4;
38 VkBuffer stagingBuffer;
39 VkDeviceMemory stagingMemory;
41 VkBufferCreateInfo bufferInfo{};
42 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
43 bufferInfo.size = imageSize;
44 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
45 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
47 if (vkCreateBuffer(m_device, &bufferInfo,
nullptr, &stagingBuffer) !=
49 SLEAK_ERROR(
"VulkanTexture: Failed to create staging buffer");
53 VkMemoryRequirements memReqs;
54 vkGetBufferMemoryRequirements(m_device, stagingBuffer, &memReqs);
56 VkMemoryAllocateInfo allocInfo{};
57 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
58 allocInfo.allocationSize = memReqs.size;
59 allocInfo.memoryTypeIndex = FindMemoryType(
60 memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
61 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
63 if (vkAllocateMemory(m_device, &allocInfo,
nullptr, &stagingMemory) !=
65 vkDestroyBuffer(m_device, stagingBuffer,
nullptr);
66 SLEAK_ERROR(
"VulkanTexture: Failed to allocate staging memory");
70 vkBindBufferMemory(m_device, stagingBuffer, stagingMemory, 0);
74 vkMapMemory(m_device, stagingMemory, 0, imageSize, 0, &mapped);
75 memcpy(mapped, data,
static_cast<size_t>(imageSize));
76 vkUnmapMemory(m_device, stagingMemory);
79 VkFormat vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
81 vkFormat = VK_FORMAT_B8G8R8A8_UNORM;
85 static_cast<uint32_t
>(std::floor(std::log2(maxDim))) + 1u;
86 if (m_maxMipLevels > 0 && m_maxMipLevels < mipLevels)
87 mipLevels = m_maxMipLevels;
90 VkFormatProperties fmtProps{};
91 vkGetPhysicalDeviceFormatProperties(m_physicalDevice, vkFormat, &fmtProps);
92 if (!(fmtProps.optimalTilingFeatures &
93 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
95 m_mipLevels = mipLevels;
98 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
99 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
100 VK_IMAGE_USAGE_SAMPLED_BIT,
102 vkDestroyBuffer(m_device, stagingBuffer,
nullptr);
103 vkFreeMemory(m_device, stagingMemory,
nullptr);
108 VkCommandBufferAllocateInfo cmdAllocInfo{};
109 cmdAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
110 cmdAllocInfo.commandPool = m_commandPool;
111 cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
112 cmdAllocInfo.commandBufferCount = 1;
113 VkCommandBuffer cmdBuffer;
114 vkAllocateCommandBuffers(m_device, &cmdAllocInfo, &cmdBuffer);
116 VkCommandBufferBeginInfo beginInfo{};
117 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
118 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
119 vkBeginCommandBuffer(cmdBuffer, &beginInfo);
121 VkImageMemoryBarrier toDst{};
122 toDst.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
123 toDst.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
124 toDst.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
125 toDst.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
126 toDst.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
127 toDst.image = m_image;
128 toDst.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
129 toDst.subresourceRange.baseMipLevel = 0;
130 toDst.subresourceRange.levelCount = mipLevels;
131 toDst.subresourceRange.baseArrayLayer = 0;
132 toDst.subresourceRange.layerCount = 1;
133 toDst.srcAccessMask = 0;
134 toDst.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
135 vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
136 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0,
139 VkBufferImageCopy region{};
140 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
141 region.imageSubresource.mipLevel = 0;
142 region.imageSubresource.baseArrayLayer = 0;
143 region.imageSubresource.layerCount = 1;
144 region.imageOffset = {0, 0, 0};
146 vkCmdCopyBufferToImage(cmdBuffer, stagingBuffer, m_image,
147 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
150 GenerateMipmaps(cmdBuffer,
static_cast<int32_t
>(
width),
151 static_cast<int32_t
>(
height));
154 VkImageMemoryBarrier toRead = toDst;
155 toRead.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
156 toRead.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
157 toRead.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
158 toRead.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
159 toRead.subresourceRange.levelCount = 1;
160 vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
161 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0,
162 nullptr, 0,
nullptr, 1, &toRead);
165 vkEndCommandBuffer(cmdBuffer);
167 VkSubmitInfo submitInfo{};
168 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
169 submitInfo.commandBufferCount = 1;
170 submitInfo.pCommandBuffers = &cmdBuffer;
171 VkFenceCreateInfo fenceInfo{};
172 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
174 vkCreateFence(m_device, &fenceInfo,
nullptr, &uploadFence);
175 vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, uploadFence);
176 vkWaitForFences(m_device, 1, &uploadFence, VK_TRUE, UINT64_MAX);
177 vkDestroyFence(m_device, uploadFence,
nullptr);
178 vkFreeCommandBuffers(m_device, m_commandPool, 1, &cmdBuffer);
181 vkDestroyBuffer(m_device, stagingBuffer,
nullptr);
182 vkFreeMemory(m_device, stagingMemory,
nullptr);
185 if (!CreateImageView(vkFormat))
return false;
186 if (!CreateSampler())
return false;
193 unsigned char* pixels =
194 stbi_load(filePath.c_str(), &w, &h, &channels, 4);
196 SLEAK_ERROR(
"VulkanTexture: Failed to load image: {}", filePath);
201 static_cast<uint32_t
>(h),
203 stbi_image_free(pixels);
218 if (m_sampler != VK_NULL_HANDLE) {
219 vkDestroySampler(m_device, m_sampler,
nullptr);
220 m_sampler = VK_NULL_HANDLE;
222 UpdateDescriptorSets();
227 m_wrapMode = wrapMode;
228 if (m_sampler != VK_NULL_HANDLE) {
229 vkDestroySampler(m_device, m_sampler,
nullptr);
230 m_sampler = VK_NULL_HANDLE;
232 UpdateDescriptorSets();
238 if (m_sampler != VK_NULL_HANDLE) {
239 vkDestroySampler(m_device, m_sampler,
nullptr);
240 m_sampler = VK_NULL_HANDLE;
242 UpdateDescriptorSets();
246void VulkanTexture::UpdateDescriptorSets() {
247 if (m_descriptorSets.empty() || m_imageView == VK_NULL_HANDLE || m_sampler == VK_NULL_HANDLE)
250 for (
auto& set : m_descriptorSets) {
251 VkDescriptorImageInfo imageInfo{};
252 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
253 imageInfo.imageView = m_imageView;
254 imageInfo.sampler = m_sampler;
256 VkWriteDescriptorSet descriptorWrite{};
257 descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
258 descriptorWrite.dstSet = set;
259 descriptorWrite.dstBinding = 0;
260 descriptorWrite.dstArrayElement = 0;
261 descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
262 descriptorWrite.descriptorCount = 1;
263 descriptorWrite.pImageInfo = &imageInfo;
265 vkUpdateDescriptorSets(m_device, 1, &descriptorWrite, 0,
nullptr);
270 if (m_imguiDescriptorSet == VK_NULL_HANDLE && m_imageView != VK_NULL_HANDLE && m_sampler != VK_NULL_HANDLE) {
271 m_imguiDescriptorSet = ImGui_ImplVulkan_AddTexture(
272 m_sampler, m_imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
274 return reinterpret_cast<uint64_t
>(m_imguiDescriptorSet);
277void VulkanTexture::Cleanup() {
278 if (m_device == VK_NULL_HANDLE)
return;
280 if (m_imguiDescriptorSet != VK_NULL_HANDLE) {
281 ImGui_ImplVulkan_RemoveTexture(m_imguiDescriptorSet);
282 m_imguiDescriptorSet = VK_NULL_HANDLE;
284 if (m_sampler != VK_NULL_HANDLE) {
285 vkDestroySampler(m_device, m_sampler,
nullptr);
286 m_sampler = VK_NULL_HANDLE;
288 if (m_imageView != VK_NULL_HANDLE) {
289 vkDestroyImageView(m_device, m_imageView,
nullptr);
290 m_imageView = VK_NULL_HANDLE;
292 if (m_image != VK_NULL_HANDLE) {
293 vkDestroyImage(m_device, m_image,
nullptr);
294 m_image = VK_NULL_HANDLE;
296 if (m_imageMemory != VK_NULL_HANDLE) {
297 vkFreeMemory(m_device, m_imageMemory,
nullptr);
298 m_imageMemory = VK_NULL_HANDLE;
302uint32_t VulkanTexture::FindMemoryType(
303 uint32_t typeFilter, VkMemoryPropertyFlags properties) {
304 VkPhysicalDeviceMemoryProperties memProperties;
305 vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties);
307 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
308 if ((typeFilter & (1 << i)) &&
309 (memProperties.memoryTypes[i].propertyFlags & properties) ==
315 SLEAK_ERROR(
"VulkanTexture: Failed to find suitable memory type");
319bool VulkanTexture::CreateImage(uint32_t
width, uint32_t
height,
321 VkImageUsageFlags usage,
322 uint32_t mipLevels) {
323 VkImageCreateInfo imageInfo{};
324 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
325 imageInfo.imageType = VK_IMAGE_TYPE_2D;
326 imageInfo.extent.width =
width;
327 imageInfo.extent.height =
height;
328 imageInfo.extent.depth = 1;
329 imageInfo.mipLevels = mipLevels;
330 imageInfo.arrayLayers = 1;
331 imageInfo.format = format;
332 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
333 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
334 imageInfo.usage = usage;
335 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
336 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
338 if (vkCreateImage(m_device, &imageInfo,
nullptr, &m_image) !=
340 SLEAK_ERROR(
"VulkanTexture: Failed to create image");
344 VkMemoryRequirements memReqs;
345 vkGetImageMemoryRequirements(m_device, m_image, &memReqs);
347 VkMemoryAllocateInfo allocInfo{};
348 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
349 allocInfo.allocationSize = memReqs.size;
350 allocInfo.memoryTypeIndex = FindMemoryType(
351 memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
353 if (vkAllocateMemory(m_device, &allocInfo,
nullptr, &m_imageMemory) !=
355 SLEAK_ERROR(
"VulkanTexture: Failed to allocate image memory");
359 vkBindImageMemory(m_device, m_image, m_imageMemory, 0);
363bool VulkanTexture::CreateImageView(VkFormat format) {
364 VkImageViewCreateInfo viewInfo{};
365 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
366 viewInfo.image = m_image;
367 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
368 viewInfo.format = format;
369 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
370 viewInfo.subresourceRange.baseMipLevel = 0;
371 viewInfo.subresourceRange.levelCount = m_mipLevels;
372 viewInfo.subresourceRange.baseArrayLayer = 0;
373 viewInfo.subresourceRange.layerCount = 1;
375 if (vkCreateImageView(m_device, &viewInfo,
nullptr, &m_imageView) !=
377 SLEAK_ERROR(
"VulkanTexture: Failed to create image view");
385void VulkanTexture::GenerateMipmaps(VkCommandBuffer cmd, int32_t
width,
387 VkImageMemoryBarrier barrier{};
388 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
389 barrier.image = m_image;
390 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
391 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
392 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
393 barrier.subresourceRange.baseArrayLayer = 0;
394 barrier.subresourceRange.layerCount = 1;
395 barrier.subresourceRange.levelCount = 1;
398 for (uint32_t i = 1; i < m_mipLevels; ++i) {
400 barrier.subresourceRange.baseMipLevel = i - 1;
401 barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
402 barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
403 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
404 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
405 vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT,
406 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0,
407 nullptr, 1, &barrier);
410 blit.srcOffsets[0] = {0, 0, 0};
411 blit.srcOffsets[1] = {mipW, mipH, 1};
412 blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
413 blit.srcSubresource.mipLevel = i - 1;
414 blit.srcSubresource.baseArrayLayer = 0;
415 blit.srcSubresource.layerCount = 1;
416 blit.dstOffsets[0] = {0, 0, 0};
417 blit.dstOffsets[1] = {mipW > 1 ? mipW / 2 : 1,
418 mipH > 1 ? mipH / 2 : 1, 1};
419 blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
420 blit.dstSubresource.mipLevel = i;
421 blit.dstSubresource.baseArrayLayer = 0;
422 blit.dstSubresource.layerCount = 1;
423 vkCmdBlitImage(cmd, m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
424 m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
428 barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
429 barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
430 barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
431 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
432 vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT,
433 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0,
434 nullptr, 0,
nullptr, 1, &barrier);
436 if (mipW > 1) mipW /= 2;
437 if (mipH > 1) mipH /= 2;
441 barrier.subresourceRange.baseMipLevel = m_mipLevels - 1;
442 barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
443 barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
444 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
445 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
446 vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT,
447 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0,
nullptr,
448 0,
nullptr, 1, &barrier);
451bool VulkanTexture::CreateSampler() {
452 VkSamplerCreateInfo samplerInfo{};
453 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
455 VkPhysicalDeviceProperties props{};
456 vkGetPhysicalDeviceProperties(m_physicalDevice, &props);
457 float deviceMaxAniso = props.limits.maxSamplerAnisotropy;
460 VkFilter magFilter = VK_FILTER_LINEAR;
461 VkFilter minFilter = VK_FILTER_LINEAR;
462 VkSamplerMipmapMode mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
463 VkBool32 anisotropyEnable = VK_FALSE;
464 float maxAnisotropy = 1.0f;
470 magFilter = VK_FILTER_NEAREST;
471 minFilter = VK_FILTER_NEAREST;
472 mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
475 mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
478 mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
481 anisotropyEnable = VK_TRUE; maxAnisotropy = 2.0f;
484 anisotropyEnable = VK_TRUE; maxAnisotropy = 4.0f;
487 anisotropyEnable = VK_TRUE; maxAnisotropy = 8.0f;
490 anisotropyEnable = VK_TRUE; maxAnisotropy = 16.0f;
497 maxAnisotropy = std::min(maxAnisotropy, deviceMaxAniso);
499 samplerInfo.magFilter = magFilter;
500 samplerInfo.minFilter = minFilter;
503 VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
504 switch (m_wrapMode) {
506 addressMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
509 addressMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
512 addressMode = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
515 addressMode = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
520 samplerInfo.addressModeU = addressMode;
521 samplerInfo.addressModeV = addressMode;
522 samplerInfo.addressModeW = addressMode;
524 samplerInfo.anisotropyEnable = anisotropyEnable;
525 samplerInfo.maxAnisotropy = maxAnisotropy;
526 samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
527 samplerInfo.unnormalizedCoordinates = VK_FALSE;
528 samplerInfo.compareEnable = VK_FALSE;
529 samplerInfo.mipmapMode = mipmapMode;
530 samplerInfo.mipLodBias = m_lodBias;
531 samplerInfo.minLod = 0.0f;
532 samplerInfo.maxLod =
static_cast<float>(m_mipLevels);
534 if (vkCreateSampler(m_device, &samplerInfo,
nullptr, &m_sampler) !=
536 SLEAK_ERROR(
"VulkanTexture: Failed to create sampler");
542void VulkanTexture::TransitionImageLayout(VkImage image,
543 VkImageLayout oldLayout,
544 VkImageLayout newLayout) {
545 VkCommandBufferAllocateInfo allocInfo{};
546 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
547 allocInfo.commandPool = m_commandPool;
548 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
549 allocInfo.commandBufferCount = 1;
551 VkCommandBuffer cmdBuffer;
552 vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
554 VkCommandBufferBeginInfo beginInfo{};
555 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
556 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
557 vkBeginCommandBuffer(cmdBuffer, &beginInfo);
559 VkImageMemoryBarrier barrier{};
560 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
561 barrier.oldLayout = oldLayout;
562 barrier.newLayout = newLayout;
563 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
564 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
565 barrier.image = image;
566 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
567 barrier.subresourceRange.baseMipLevel = 0;
568 barrier.subresourceRange.levelCount = 1;
569 barrier.subresourceRange.baseArrayLayer = 0;
570 barrier.subresourceRange.layerCount = 1;
572 VkPipelineStageFlags srcStage;
573 VkPipelineStageFlags dstStage;
575 if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED &&
576 newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
577 barrier.srcAccessMask = 0;
578 barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
579 srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
580 dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
581 }
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
582 newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
583 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
584 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
585 srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
586 dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
588 barrier.srcAccessMask = 0;
589 barrier.dstAccessMask = 0;
590 srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
591 dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
594 vkCmdPipelineBarrier(cmdBuffer, srcStage, dstStage, 0, 0,
nullptr, 0,
595 nullptr, 1, &barrier);
597 vkEndCommandBuffer(cmdBuffer);
599 VkSubmitInfo submitInfo{};
600 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
601 submitInfo.commandBufferCount = 1;
602 submitInfo.pCommandBuffers = &cmdBuffer;
604 VkFenceCreateInfo fenceInfo{};
605 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
607 vkCreateFence(m_device, &fenceInfo,
nullptr, ©Fence);
608 vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, copyFence);
609 vkWaitForFences(m_device, 1, ©Fence, VK_TRUE, UINT64_MAX);
610 vkDestroyFence(m_device, copyFence,
nullptr);
611 vkFreeCommandBuffers(m_device, m_commandPool, 1, &cmdBuffer);
void Bind(uint32_t slot=0) const override
VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue graphicsQueue)
void Unbind() const override
void SetWrapMode(TextureWrapMode wrapMode) override
uint64_t GetImGuiTextureID() const override
void SetLodBias(float bias) override
void SetFilter(TextureFilter filter) override
bool LoadFromFile(const std::string &filePath) override
Decodes an image file and uploads it as a new Vulkan image.
bool LoadFromMemory(const void *data, uint32_t width, uint32_t height, TextureFormat format) override
Uploads raw pixel data through a staging buffer and generates mips.
~VulkanTexture() override
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.