MNN/source/backend/vulkan/component/VulkanImage.cpp

127 lines
4.7 KiB
C++
Raw Normal View History

2019-04-17 10:49:11 +08:00
//
// VulkanImage.cpp
// MNN
//
// Created by MNN on 2019/01/31.
// Copyright © 2018, Alibaba Group Holding Limited
//
2019-12-27 22:16:57 +08:00
#include "backend/vulkan/component/VulkanImage.hpp"
2019-04-17 10:49:11 +08:00
#include <string.h>
namespace MNN {
VulkanSampler::VulkanSampler(const VulkanDevice& dev, VkFilter filter, VkSamplerAddressMode mode) : mDevice(dev) {
// Finally, create a sampler.
CALL_VK(mDevice.createSampler(mSampler, filter, mode));
}
VulkanSampler::~VulkanSampler() {
mDevice.destroySampler(mSampler);
}
void VulkanImage::release() {
2020-12-15 14:12:35 +08:00
if (nullptr == mMemory.first) {
2019-04-17 10:49:11 +08:00
return;
}
const_cast<VulkanMemoryPool&>(mPool).returnMemory(mMemory);
2020-12-15 14:12:35 +08:00
mMemory.first = nullptr;
2019-04-17 10:49:11 +08:00
}
2023-12-04 11:12:20 +08:00
VulkanImage::VulkanImage(const VulkanMemoryPool& pool, bool separate, const std::vector<int>& dims, VkFormat format, VkImageUsageFlags usage)
: mDevice(pool.device()), mPool(pool) {
2023-12-04 11:12:20 +08:00
if (format == VK_FORMAT_R32G32B32A32_SFLOAT && pool.permitFp16()) {
// FIXME: find better method
format = VK_FORMAT_R16G16B16A16_SFLOAT;
}
2019-04-17 10:49:11 +08:00
MNN_ASSERT(dims.size() >= 1 && dims.size() <= 3);
auto imageType = VK_IMAGE_TYPE_1D;
auto viewType = VK_IMAGE_VIEW_TYPE_1D;
mDims = dims;
2020-11-05 16:41:56 +08:00
auto mWidth = dims[0];
auto mHeight = 1;
auto mDepth = 1;
2019-04-17 10:49:11 +08:00
if (dims.size() > 1) {
mHeight = dims[1];
imageType = VK_IMAGE_TYPE_2D;
viewType = VK_IMAGE_VIEW_TYPE_2D;
}
if (dims.size() > 2) {
mDepth = dims[2];
imageType = VK_IMAGE_TYPE_3D;
viewType = VK_IMAGE_VIEW_TYPE_3D;
}
2020-11-05 16:41:56 +08:00
auto mFormat = format;
mInfo = std::make_tuple(imageType, mWidth, mHeight, mDepth, mFormat);
2019-04-17 10:49:11 +08:00
// FUNC_PRINT(format);
2023-12-04 11:12:20 +08:00
CALL_VK(mDevice.createImage(mImage.first, imageType, mWidth, mHeight, mDepth, mFormat, usage));
2019-04-17 10:49:11 +08:00
VkMemoryRequirements memRequirements;
2020-11-05 16:41:56 +08:00
mDevice.getImageMemoryRequirements(mImage.first, memRequirements);
2019-04-17 10:49:11 +08:00
2022-05-27 23:46:44 +08:00
mMemory = const_cast<VulkanMemoryPool&>(mPool).allocMemory(memRequirements, 0, separate);
2019-04-17 10:49:11 +08:00
// FUNC_PRINT(mMemory->type());
2020-12-15 14:12:35 +08:00
auto realMem = (VulkanMemory*)mMemory.first;
mDevice.bindImageMemory(mImage.first, realMem->get(), mMemory.second);
2020-11-05 16:41:56 +08:00
CALL_VK(mDevice.createImageView(mImage.second, mImage.first, viewType, format));
2019-04-17 10:49:11 +08:00
}
VulkanImage::~VulkanImage() {
2020-11-05 16:41:56 +08:00
mDevice.destroyImageView(mImage.second, nullptr);
2023-12-04 11:12:20 +08:00
mDevice.destroyImage(mImage.first);
2020-12-15 14:12:35 +08:00
if (nullptr != mMemory.first) {
2020-11-05 16:41:56 +08:00
const_cast<VulkanMemoryPool&>(mPool).returnMemory(mMemory);
2019-04-17 10:49:11 +08:00
}
}
void VulkanImage::barrierWrite(VkCommandBuffer buffer) const {
2023-12-04 11:12:20 +08:00
VkImageSubresourceRange subrange;
::memset(&subrange, 0, sizeof(VkImageSubresourceRange));
2023-12-04 11:12:20 +08:00
subrange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subrange.layerCount = 1;
subrange.levelCount = 1;
insertMemoryBarrier(buffer, mImage.first, mAccess, VK_ACCESS_SHADER_WRITE_BIT, mLayout, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, subrange);
mLayout = VK_IMAGE_LAYOUT_GENERAL;
mAccess = VK_ACCESS_SHADER_WRITE_BIT;
}
void VulkanImage::barrierRead(VkCommandBuffer buffer) const {
if (mAccess == VK_ACCESS_SHADER_READ_BIT && mLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
return;
}
2023-12-04 11:12:20 +08:00
VkImageSubresourceRange subrange;
::memset(&subrange, 0, sizeof(VkImageSubresourceRange));
2023-12-04 11:12:20 +08:00
subrange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subrange.layerCount = 1;
subrange.levelCount = 1;
insertMemoryBarrier(buffer, mImage.first, mAccess, VK_ACCESS_SHADER_READ_BIT, mLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, subrange);
mLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
mAccess = VK_ACCESS_SHADER_READ_BIT;
}
2023-12-04 11:12:20 +08:00
void VulkanImage::insertMemoryBarrier(
VkCommandBuffer cmdbuffer,
VkImage image,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
VkImageLayout oldImageLayout,
VkImageLayout newImageLayout,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageSubresourceRange subresourceRange
) {
VkImageMemoryBarrier imageMemoryBarrier;
::memset(&imageMemoryBarrier, 0, sizeof(VkImageMemoryBarrier));
imageMemoryBarrier.srcAccessMask = srcAccessMask;
imageMemoryBarrier.dstAccessMask = dstAccessMask;
imageMemoryBarrier.oldLayout = oldImageLayout;
imageMemoryBarrier.newLayout = newImageLayout;
imageMemoryBarrier.image = image;
imageMemoryBarrier.subresourceRange = subresourceRange;
vkCmdPipelineBarrier(
cmdbuffer,
srcStageMask,
dstStageMask,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
}
2019-04-17 10:49:11 +08:00
} // namespace MNN