|
|
|
@ -1,10 +1,10 @@ |
|
|
|
|
#include "vulkan/image.hpp" |
|
|
|
|
#include "vulkan/instance.hpp" |
|
|
|
|
#include "vulkan/buffer.hpp" |
|
|
|
|
|
|
|
|
|
#include "vulkan/command_pool.hpp" |
|
|
|
|
|
|
|
|
|
Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, |
|
|
|
|
VkImageUsageFlags usage) : format(format) { |
|
|
|
|
VkImageUsageFlags usage) : format(format), width(width), height(height) { |
|
|
|
|
|
|
|
|
|
VkImageCreateInfo imageCreateInfo {}; |
|
|
|
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; |
|
|
|
@ -30,14 +30,20 @@ Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling til |
|
|
|
|
|
|
|
|
|
Image::Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, |
|
|
|
|
VkImageUsageFlags usage) : Image(width, height, format, tiling, usage){ |
|
|
|
|
|
|
|
|
|
Buffer stagingBuffer(size, initialData, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); |
|
|
|
|
|
|
|
|
|
transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
|
|
|
|
stagingBuffer.copyTo(this); |
|
|
|
|
|
|
|
|
|
transitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Image::~Image() { |
|
|
|
|
if (view) |
|
|
|
|
vkDestroyImageView(Instance::GetDevice(), view, nullptr); |
|
|
|
|
if (sampler) |
|
|
|
|
vkDestroySampler(Instance::GetDevice(), sampler, nullptr); |
|
|
|
|
vmaDestroyImage(Instance::GetAllocator(), handle, allocation); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -61,6 +67,73 @@ VkImageView Image::createView(VkImageAspectFlags aspectFlags) { |
|
|
|
|
return view; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
VkSampler Image::createSampler() { |
|
|
|
|
VkSamplerCreateInfo samplerInfo {}; |
|
|
|
|
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; |
|
|
|
|
samplerInfo.magFilter = VK_FILTER_LINEAR; |
|
|
|
|
samplerInfo.minFilter = VK_FILTER_LINEAR; |
|
|
|
|
|
|
|
|
|
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |
|
|
|
|
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |
|
|
|
|
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |
|
|
|
|
|
|
|
|
|
samplerInfo.anisotropyEnable = VK_FALSE; |
|
|
|
|
samplerInfo.maxAnisotropy = 1.0; |
|
|
|
|
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; |
|
|
|
|
samplerInfo.unnormalizedCoordinates = VK_FALSE; |
|
|
|
|
samplerInfo.compareEnable = VK_FALSE; |
|
|
|
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; |
|
|
|
|
|
|
|
|
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; |
|
|
|
|
samplerInfo.mipLodBias = 0.0f; |
|
|
|
|
samplerInfo.minLod = 0.0; |
|
|
|
|
samplerInfo.maxLod = 0.0; |
|
|
|
|
|
|
|
|
|
vkCreateSampler(Instance::GetDevice(), &samplerInfo, nullptr, &sampler); |
|
|
|
|
|
|
|
|
|
return sampler; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) { |
|
|
|
|
auto commandPool = Instance::instance->renderingCommandPool; |
|
|
|
|
auto commandBuffer = commandPool->beginSingleTimeCommandBuffer(); |
|
|
|
|
|
|
|
|
|
VkImageMemoryBarrier barrier {}; |
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; |
|
|
|
|
barrier.oldLayout = oldLayout; |
|
|
|
|
barrier.newLayout = newLayout; |
|
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
|
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
|
|
|
|
barrier.image = handle; |
|
|
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
|
|
|
|
barrier.subresourceRange.levelCount = 1; |
|
|
|
|
barrier.subresourceRange.baseMipLevel = 0; |
|
|
|
|
barrier.subresourceRange.layerCount = 1; |
|
|
|
|
barrier.subresourceRange.baseArrayLayer = 0; |
|
|
|
|
|
|
|
|
|
VkPipelineStageFlags sourceStage = 0; |
|
|
|
|
VkPipelineStageFlags destinationStage = 0; |
|
|
|
|
|
|
|
|
|
if ((oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL){ |
|
|
|
|
barrier.srcAccessMask = 0; |
|
|
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
|
|
|
|
|
|
|
|
|
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; |
|
|
|
|
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; |
|
|
|
|
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL){ |
|
|
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
|
|
|
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; |
|
|
|
|
|
|
|
|
|
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; |
|
|
|
|
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vkCmdPipelineBarrier(commandBuffer, |
|
|
|
|
sourceStage, destinationStage, |
|
|
|
|
0, |
|
|
|
|
0, nullptr, |
|
|
|
|
0, nullptr, |
|
|
|
|
1, &barrier); |
|
|
|
|
|
|
|
|
|
commandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue); |
|
|
|
|
} |
|
|
|
|